JMH 是 Java 的微基准测试工具,由 OpenJDK 团队开发,专门用于编写、运行和分析 Java 代码的微基准测试(microbenchmark)。
为什么需要 JMH
普通的基准测试方法(如多次循环调用方法并计时)存在很多问题:
JVM 的 JIT 编译优化(方法内联、死代码消除等)
预热效应(JVM 需要"热身"才能达到最佳性能)
垃圾回收的干扰
操作系统调度的影响
JMH 解决了这些问题,提供了准确的基准测试环境。
基本使用
1. 添加依赖
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.37</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.37</version>
<scope>provided</scope>
</dependency>
2. 编写基准测试
import org.openjdk.jmh.annotations.*;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.AverageTime) // 测试模式:平均时间
@OutputTimeUnit(TimeUnit.NANOSECONDS) // 输出时间单位
@State(Scope.Thread) // 每个测试线程一个实例
public class MyBenchmark {
@Param({"10", "100", "1000"}) // 参数化测试
private int length;
private int[] array;
@Setup // 初始化方法
public void setup() {
array = new int[length];
// 初始化数组...
}
@Benchmark // 基准测试方法
public int testMethod() {
// 被测代码
int sum = 0;
for (int i : array) {
sum += i;
}
return sum;
}
}
3. 运行基准测试
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
public class BenchmarkRunner {
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(MyBenchmark.class.getSimpleName())
.forks(1) // 使用1个进程
.warmupIterations(5) // 预热5次
.measurementIterations(5) // 正式测量5次
.build();
new Runner(opt).run();
}
}
常用注解
注解 | 说明 |
---|---|
@Benchmark |
标记基准测试方法 |
@BenchmarkMode |
测试模式:Throughput(吞吐量)、AverageTime(平均时间)、SampleTime(采样时间)等 |
@OutputTimeUnit |
结果时间单位 |
@State |
定义测试状态的作用域 (Scope.Thread/Benchmark/Group) |
@Setup |
测试前的初始化方法 |
@TearDown |
测试后的清理方法 |
@Param |
参数化测试字段 |
@Fork |
指定fork次数(隔离测试) |
@Warmup |
预热配置 |
@Measurement |
正式测量配置 |
最佳实践
避免死代码消除:确保基准测试方法有返回值或副作用
合理设置预热:通常3-5次预热迭代
使用
@State
管理状态:避免在基准测试方法中初始化多次测量:增加测量次数提高准确性
参数化测试:使用
@Param
测试不同输入规模避免系统干扰:关闭其他程序,保持测试环境稳定
高级特性
Profiler支持:集成各种分析器(GC、堆栈等)
异步profiling:不影响基准测试运行
时间控制:精确控制测试时间
多线程测试:评估并发性能
典型输出示例
Benchmark (length) Mode Cnt Score Error Units
MyBenchmark.testMethod 10 avgt 5 15.234 ± 0.123 ns/op
MyBenchmark.testMethod 100 avgt 5 142.567 ± 1.234 ns/op
MyBenchmark.testMethod 1000 avgt 5 1356.789 ± 12.345 ns/op
JMH 是 Java 性能测试的事实标准工具,特别适合比较不同算法或实现的性能差异。