JMH入门实战,这篇就够了

一、JMH介绍

1.1 JMH是什么

JMH(Java Microbenchmark Harness)是一个Micro Benchmark Framework(微基准测试框架),一个java工具,可以简单的理解成method层面的benchmark测试,可以精确到微秒级。不仅可以测试java代码还可以测试其他jvm上的程序

1.2 为什么需要基准测试

简单地说,基准测试是针对系统设计的一种压力测试。真正的性能都不能通过估计的方式来进行优化的,必须要有专业的测试工具,全面、仔细、专业的展示被测试代码的性能。

二、JMH基础使用

2.1 POM依赖

<properties>
    <jmh.version>1.14.1</jmh.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.openjdk.jmh</groupId>
        <artifactId>jmh-core</artifactId>
        <version>${jmh.version}</version>
    </dependency>
    <dependency>
        <groupId>org.openjdk.jmh</groupId>
        <artifactId>jmh-generator-annprocess</artifactId>
        <version>${jmh.version}</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

2.2 BenchMark代码

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@State(Scope.Thread)
public class FirstBenchmark {

    @Benchmark
    @SneakyThrows
    public int sleepAWhile() {
        Thread.sleep(500);
        return 0;
    }
	// 如果在idea中执行必须使用run模式,而不是debug模式,否则JMH框架依赖的JDWP会报错
    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
		        // 指定要测试的方法所在类
                .include(FirstBenchmark.class.getSimpleName())
                // 进行几个线程测试就forks几个
                .forks(1)
                // 热启动,JIT相关的,冷启动则设置为0
                .warmupIterations(5)
                // 迭代测试次数
                .measurementIterations(5)
                .build();

        new Runner(opt).run();
    }
}

其中sleepAWhile就是要被测试性能的方法,main调用JMHapi来进行性能测试。

2.2.1 @BenchmarkMode(Mode.AverageTime)

其中@BenchmarkMode(Mode.AverageTime)声明要测试的类型,该注解可以作用在方法上、类上支持如下(定义于: org.openjdk.jmh.annotations.Mode)

  1. Throughput吞吐量
  2. Average Time 平均时间
  3. Sample Time 抽样统计时间(包括最大最小等)
  4. Single Shot Time 单发时间(常用于冷启动)
  5. All 所有的指标

2.2.2 @OutputTimeUnit(TimeUnit.MICROSECONDS)

以指定单位打印BenchMark测试结果。支持单位如下

  1. NANOSECONDS 纳秒
  2. MICROSECONDS 微秒
  3. MILLISECONDS 毫秒
  4. SECONDS 几秒钟
  5. MINUTES 分钟
  6. HOURS 时间
  7. DAYS 天数

2.2.3 @State(Scope.Thread)

用于关联一些BenchMark测试需要的变量,如下代码举例:

public class MyBenchmark {

    @State(Scope.Thread) 
    public static class MyState { // 静态内部类
        public int a = 1;
        public int b = 2;
        public int sum ;
    }


    @Benchmark @BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.MINUTES)
    public void testMethod(MyState state) {
        state.sum = state.a + state.b;
    }

}

@State向JHM框架表名这是一个state类。被@State注解注上的类有如下约束:

  1. 类必须是public
  2. 如果是静态的话还必须是static的
  3. 类必须有一个无参构造函数

2.2.4 @Benchmark

类似与@Test在Junit框架里的作用。

2.2.5 @SetUp

方法级注解,这个注解的作用就是我们需要在测试之前进行一些准备工作,比如对一些数据的初始化之类的。类似与Junit的@before

2.2.6 @TearDown

方法级注解,这个注解的作用就是我们需要在测试之后进行一些结束工作,比如关闭线程池,数据库连接等的,主要用于资源的回收等。类似junit的@after

三、JHM实战注意

  1. 一般不要在循环里使用JHM,必须非预期的JVM循环优化
  2. 避免常数优化,参考这里
  3. 没有代码调用的代码块会被JVM忽略,甚至都不执行,例如:
   @Benchmark
    public void testMethod() {
        int a = 1;
        int b = 2;
        int sum = a + b;
        // 可以设置返回值,避免`死码`问题
    }

四、相关链接

  1. JMH idea 插件
  2. JMH代码示例大全
  3. JMH github

五、参考链接

  1. JMH - Java Microbenchmark Harness
  2. Java 并发编程笔记:JMH 性能测试框架
  3. Java微基准测试框架JMH
  4. 为什么需要基准测试

博主其他文章

响应式编程

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值