JMH入门

2022-09-18 15:19:59 浏览数 (1)

大家好,又见面了,我是你们的朋友全栈君。

1 JMH介绍

JMH是Java Micro Benchmark Harness的简写,是专门用于代码微基准测试的工具集(toolkit)。JMH是由实现Java虚拟机的团队开发的,因此他们非常清楚开发者所编写的代码在虚拟机中将会如何执行。 由于现代JVM已经变得越来越智能,在Java文件的编译阶段、类的加载阶段,以及运行阶段都可能进行了不同程度的优化,因此开发者编写的代码在运行中未必会像自己所预期的那样具有相同的性能体现,JVM的开发者为了让普通开发者能够了解自己所编写的代码运行的情况,JMH便因此而生。

JMH的官网地址:地址

maven坐标:

代码语言:javascript复制
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-core</artifactId>
    <version>1.19</version>
</dependency>
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-generator-annprocess</artifactId>
    <version>1.19</version>
    <scope>provided</scope>
</dependency>

2 JMH快速入门

对比一下ArrayList和LinkedList这两者的add方法在性能上的差异:

代码语言:javascript复制
import org.openjdk.jmh.annotations.*;
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;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/** * @author wyaoyao * @date 2021/4/13 18:02 */
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@State(Scope.Thread)
public class JMHExample01 { 
   

    private final static String DATA = "DUMMY DATA";

    private List<String> arrayList;
    private List<String> linkedList;

    @Setup(Level.Iteration)
    public void setUp() { 
   
        this.arrayList = new ArrayList<>();
        this.linkedList = new LinkedList<>();
    }

    @Benchmark
    public List<String> arrayListAdd() { 
   
        this.arrayList.add(DATA);
        return arrayList;
    }

    @Benchmark
    public List<String> linkedListAdd() { 
   
        this.linkedList.add(DATA);
        return this.linkedList;
    }

    public static void main(String[] args) throws RunnerException { 
   

        final Options opts = new OptionsBuilder()
                .include(JMHExample01.class.getSimpleName())
                .forks(1)
                .measurementIterations(10)
                .warmupIterations(10)
                .build();
        new Runner(opts).run();
    }
}

运行输出:

代码语言:javascript复制
# JMH version: 1.19
# VM version: JDK 1.8.0_275, VM 25.275-b01
# VM invoker: C:Program FilesAdoptOpenJDKjdk-8.0.275.1-hotspotjrebinjava.exe
# VM options: -javaagent:C:Program FilesJetBrainsIntelliJ IDEA 2020.2.2libidea_rt.jar=60744:C:Program FilesJetBrainsIntelliJ IDEA 2020.2.2bin -Dfile.encoding=UTF-8
# Warmup: 10 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Average time, time/op
# Benchmark: study.wyy.juc.jmh.JMHExample01.arrayListAdd

# Run progress: 0.00% complete, ETA 00:00:40
# Fork: 1 of 1
# Warmup Iteration   1: 0.019 us/op
# Warmup Iteration   2: 0.015 us/op
# Warmup Iteration   3: 0.016 us/op
# Warmup Iteration   4: 0.016 us/op
# Warmup Iteration   5: 0.023 us/op
# Warmup Iteration   6: 0.016 us/op
# Warmup Iteration   7: 0.016 us/op
# Warmup Iteration   8: 0.016 us/op
# Warmup Iteration   9: 0.015 us/op
# Warmup Iteration  10: 0.014 us/op
Iteration   1: 0.012 us/op
Iteration   2: 0.012 us/op
Iteration   3: 0.035 us/op
Iteration   4: 0.045 us/op
Iteration   5: 0.032 us/op
Iteration   6: 0.034 us/op
Iteration   7: 0.034 us/op
Iteration   8: 0.042 us/op
Iteration   9: 0.032 us/op
Iteration  10: 0.039 us/op


Result "study.wyy.juc.jmh.JMHExample01.arrayListAdd":
  0.032 ±(99.9%) 0.017 us/op [Average]
  (min, avg, max) = (0.012, 0.032, 0.045), stdev = 0.011
  CI (99.9%): [0.015, 0.049] (assumes normal distribution)


# JMH version: 1.19
# VM version: JDK 1.8.0_275, VM 25.275-b01
# VM invoker: C:Program FilesAdoptOpenJDKjdk-8.0.275.1-hotspotjrebinjava.exe
# VM options: -javaagent:C:Program FilesJetBrainsIntelliJ IDEA 2020.2.2libidea_rt.jar=60744:C:Program FilesJetBrainsIntelliJ IDEA 2020.2.2bin -Dfile.encoding=UTF-8
# Warmup: 10 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Average time, time/op
# Benchmark: study.wyy.juc.jmh.JMHExample01.linkedListAdd

# Run progress: 50.00% complete, ETA 00:00:30
# Fork: 1 of 1
# Warmup Iteration   1: 0.559 us/op
# Warmup Iteration   2: 0.318 us/op
# Warmup Iteration   3: 0.344 us/op
# Warmup Iteration   4: 0.139 us/op
# Warmup Iteration   5: 0.295 us/op
# Warmup Iteration   6: 0.096 us/op
# Warmup Iteration   7: 0.101 us/op
# Warmup Iteration   8: 0.097 us/op
# Warmup Iteration   9: 0.102 us/op
# Warmup Iteration  10: 0.098 us/op
Iteration   1: 0.285 us/op
Iteration   2: 0.094 us/op
Iteration   3: 0.280 us/op
Iteration   4: 0.091 us/op
Iteration   5: 0.279 us/op
Iteration   6: 0.092 us/op
Iteration   7: 0.100 us/op
Iteration   8: 0.294 us/op
Iteration   9: 0.094 us/op
Iteration  10: 0.108 us/op


Result "study.wyy.juc.jmh.JMHExample01.linkedListAdd":
  0.172 ±(99.9%) 0.147 us/op [Average]
  (min, avg, max) = (0.091, 0.172, 0.294), stdev = 0.097
  CI (99.9%): [0.025, 0.319] (assumes normal distribution)


# Run complete. Total time: 00:01:28

Benchmark                   Mode  Cnt  Score   Error  Units
JMHExample01.arrayListAdd   avgt   10  0.032 ± 0.017  us/op
JMHExample01.linkedListAdd  avgt   10  0.172 ± 0.147  us/op

目前我们只需要查看输出的最后两行,大体上,我们从这两行信息可以发现arrayListAdd方法的调用平均响应时间为0.032微秒,误差在0.017微秒,而linkedListAdd方法的调用平均响应时间为0.172微秒,误差在0.147微秒

3 相关注解解释

3.1 @Benchmark注解标记基准测试方法

与Junit4.x版本需要使用@Test注解标记单元测试方法一样,JMH对基准测试的方法需要使用@Benchmark注解进行标记,否则方法将被视为普通方法,并且不会对其执行基准测试。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/157721.html原文链接:https://javaforall.cn

0 人点赞