1、依赖
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.35</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.35</version>
</dependency>
2、注解
@BenchmarkMode
JMH能够以不同的模式来执行基准测试,JMH支持如下几种模式:
- Throughput:吞吐率,即每秒被测试方法被执行的次数
- Average Time:方法平均执行耗时
- Sample Time:随机采样,展示其分布
- Single Shot Time:只执行一次,获取其耗时,一般用于测试冷启动的性能。
@State
用于定义作用范围。
- Scope.Benchmark:所有测试线程共享一个实例,测试有状态实例在多线程共享下的性能
- Scope.Group:同一个线程在同一个 group 里共享实例
- Scope.Thread:默认的 State,每个测试线程分配一个实例
@Warmup
预热配置参数。
- iterations:预热的次数
- time:每次预热的时间
- timeUnit:时间的单位,默认秒
- batchSize:批处理大小,每次操作调用几次方法
@Threads
每个测试进程的测试线程数
@Fork
进行 fork 的次数,可用于类或者方法上。如果 fork 数是 2 的话,则 JMH 会 fork 出两个进程来进行测试。
@OutputTimeUnit
测试结果的时间单位
@Measurement
实际调用方法所需要配置的一些基本测试参数
- iterations:执行的次数。
- time:每次执行的时间。
- timeUnit:时间单位,默认是s。
- batchSize:批处理大小,每次操作调用几次方法。
@Param
指定某项参数的多种情况,特别适合用来测试一个函数在不同的参数输入的情况下的性能,只能作用在字段上,使用该注解必须定义 @State 注解。
@Setup
必须标示在@State注解的类内部,表示初始化操作
@TearDown
必须表示在@State注解的类内部,表示销毁操作
3、启动
Options opt = new OptionsBuilder()
.include(Test19.class.getSimpleName())
.forks(1)
.result("result1.json")
.resultFormat(ResultFormatType.JSON)
.build();
new Runner(opt).run();
4、可视化
JMH测试结果是一个json串,我们也可以通过一些工具进行可视化直观展示。
- JMH Visual Chart:http://deepoove.com/jmh-visual-chart/
- JMH Visualizer:https://jmh.morethan.io/
5、示例
@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 3, time = 1)
@Measurement(iterations = 5, time = 5)
@Threads(4)
@Fork(1)
@State(value = Scope.Benchmark)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class Test {
public static List<String> list = Lists.newArrayList();
static {
for (int i = 0; i < 100; i++) {
list.add(i + "-");
}
}
@Benchmark
public void streamtest() {
List<String> aFor = list.stream().map(s -> new StringBuffer(s).append("for").toString()).collect(Collectors.toList());
}
@Benchmark
public void fortest() {
List<String> lis = Lists.newArrayList();
for (String s : list) {
lis.add(new StringBuffer(s).append("for").toString());
}
}
@Benchmark
public void fortest2() {
List<String> lis = Lists.newArrayListWithCapacity(list.size());
for (String s : list) {
lis.add(new StringBuffer(s).append("for").toString());
}
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(Test19.class.getSimpleName())
.forks(1)
.result("result1.json")
.resultFormat(ResultFormatType.JSON)
.build();
new Runner(opt).run();
}
}