在看Spring源码时, 可以看到有些子项目之下, 有jmh模块, 这个模块是用来做什么的呢?
JMH(Java Microbenchmark Harness), openjdk提供的测试框架, 可以用来做微基准测试.
关于基准测试, 可以查看百度百科. 百度百科-基准测试
那么, 一个Java项目怎么做JMH? 先运行一个简单的demo
技术栈:
-
JDK版本
JDK8
-
构建工具
gradle
-
jmh版本
1.33
build.gradle
当前示例使用的是Main方法测试的, 如果是单元测试, 导入依赖时, 要使用testImplementation而不是implementation
dependencies {
//......
// jmh
implementation('org.openjdk.jmh:jmh-core:1.33')
annotationProcessor("org.openjdk.jmh:jmh-generator-annprocess:1.33")
//......
}
ArrayJmh.java
测试Java数组和ArrayList循环赋值性能
// 基准测试模式
@BenchmarkMode({Mode.SampleTime, Mode.AverageTime})
// 预热参数 > 预热迭代次数;每次预热迭代的时间;预热迭代持续时间的时间单位;每个操作的基准方法调用次数
@Warmup(iterations = 0, time = 500, timeUnit = TimeUnit.MILLISECONDS, batchSize = 1)
// 测量参数 > 测量迭代次数;每次测量迭代的时间;测量迭代持续时间的时间单位;每个操作的基准方法调用次数
@Measurement(iterations = 1, time = 500, timeUnit = TimeUnit.MILLISECONDS, batchSize = 1)
// 运行的线程数
@Threads(1)
// 分叉参数 > 分叉的次数;
@Fork(0)
// 标记状态对象: 基准状态范围
@State(Scope.Benchmark)
// 事件单位
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public class ArrayJhm {
@Param({"10"})
private int len;
@Param({"10"})
private int size;
@Benchmark
public void arrayMark(Blackhole blackhole){
Integer[] array = new Integer[len];
for (int i=0; i < len; i++) {
array[i] = i;
}
blackhole.consume(array);
}
@Benchmark
public void listList(Blackhole blackhole){
List<Integer> list = new ArrayList<>();
for (int i=0; i < size; i++) {
list.add(i);
}
blackhole.consume(list);
}
public static void main(String[] args) throws RunnerException {
Options options = new OptionsBuilder()
.include(ArrayJhm.class.getSimpleName())
.result("mark/mark."+ DateUtil.formatDateTime(new Date()) +".json")
.resultFormat(ResultFormatType.JSON)
.build();
new Runner(options).run();
}
}
执行main方法, 可以打印出具体的性能数据
可以看出, 在此情况下, 数组的性能要高于arrayList
也可以在代码中指定到处数据, 将导出的数据导入到网上的工具网站, 可以更直观的观看性能数据
例如: jmh-visual-chart
当前示例只是为了跑通环境, 后续继续探索JMH的神奇功能
PS, 如果出现下述错误
Exception in thread "main" java.lang.RuntimeException: ERROR: Unable to find the resource: /META-INF/BenchmarkList
at org.openjdk.jmh.runner.AbstractResourceReader.getReaders(AbstractResourceReader.java:98)
at org.openjdk.jmh.runner.BenchmarkList.find(BenchmarkList.java:124)
at org.openjdk.jmh.runner.Runner.internalRun(Runner.java:253)
at org.openjdk.jmh.runner.Runner.run(Runner.java:209)
at jin.panpan.jmh.ArrayJhm.main(ArrayJhm.java:67)
是因为执行过程中没有加载到 jmh-generator-annprocess
导致的, 需要根据代码, 按生命周期导入包.