JMH (Java Microbenchmark Harness)

发布于:2025-06-28 ⋅ 阅读:(19) ⋅ 点赞:(0)

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 正式测量配置

最佳实践

  1. 避免死代码消除:确保基准测试方法有返回值或副作用

  2. 合理设置预热:通常3-5次预热迭代

  3. 使用@State管理状态:避免在基准测试方法中初始化

  4. 多次测量:增加测量次数提高准确性

  5. 参数化测试:使用@Param测试不同输入规模

  6. 避免系统干扰:关闭其他程序,保持测试环境稳定

高级特性

  • 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 性能测试的事实标准工具,特别适合比较不同算法或实现的性能差异。


网站公告

今日签到

点亮在社区的每一天
去签到