# 使用JMH做代码性能测试

# 简介

在开发过程中,我们经常需要对代码性能进行测试,特别是涉及到算法的地方,可能会有多种算法实现方式,这时我们需要对每种实现的性能进行测试。告别手动的简单计时统计,推荐使用OpenJDK的微基准测试套件JMH。

# 使用

  • JDK9以前需要引入JMH的依赖,JDK9以后就自带了
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-core</artifactId>
    <version>1.23</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-generator-annprocess</artifactId>
    <version>1.23</version>
    <scope>test</scope>
</dependency>
  • 编写测试用例
public class JMHTest {

    @Benchmark
    @BenchmarkMode(Mode.AverageTime)
    @OutputTimeUnit(TimeUnit.SECONDS)
    @Warmup(iterations = 2, time = 1, timeUnit = TimeUnit.SECONDS)
    @Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
    @Fork(1)
    public void t(){
        for (int i = 0; i < 1000; i++) {
            System.out.print(i+",");
        }
    }

    @Test
    public void t2() throws RunnerException {
        // 启动基准测试
        Options opt = new OptionsBuilder()
                // 要导入的测试类
                .include(JMHTest.class.getSimpleName())
                // 输出测试结果的文件
                //.output("D:\\jmh.log")
                .build();
        new Runner(opt).run(); // 执行测试
    }
}

  • 参数说明 OptionsBuilder用于构造基准测试相关的参数,上面的示例将参数使用注解的方式提供了,也可以在OptionsBuilder中通过编码的方式提供。
    @Benchmark:指定一个测试基准测试方法,启动后会扫描有这个注解的方法进行基准测试;
    @BenchmarkMode:基准测试模式,有Throughput(吞吐量)、AverageTime(平均时间)、SampleTime(随机采样)、SingleShotTime(在每次执行中统计时间)、All,上面示例采用AverageTime,即统计平均耗时;
    @OutputTimeUnit:输出时间单位为秒;
    @Warmup:预热,上面示例预热2轮,每轮执行1秒时间;
    @Measurement:真实执行 @Fork:相当于执行几轮

  • 示例输出

Result "com.eason.JMHTest.t":
  0.005 ±(99.9%) 0.001 s/op [Average]
  (min, avg, max) = (0.005, 0.005, 0.005), stdev = 0.001
  CI (99.9%): [0.005, 0.006] (assumes normal distribution)

Benchmark  Mode  Cnt  Score    Error  Units
JMHTest.t  avgt    5  0.005 ±  0.001   s/op