jmh使用

一.概述

1.定义:JMH,即Java Microbenchmark Harness,是专门用于代码微基准测试的工具套件
2.应用场景
想定量地知道某个函数需要执行多长时间,以及执行时间和输入 n 的相关性
一个函数有两种不同实现(例如实现 A 使用了 FixedThreadPool,实现 B 使用了 ForkJoinPool),不知道哪种实现性能更好
3.注解介绍

  • @BenchmarkMode(Mode.Throughput)
    Mode 表示 JMH 进行 Benchmark 时所使用的模式。通常是测量的维度不同,或是测量的方式不同。目前 JMH 共有四种模式:
    (1).Throughput: 整体吞吐量,例如“1秒内可以执行多少次调用”。
    (2).AverageTime: 调用的平均时间,例如“每次调用平均耗时xxx毫秒”。
    (3).SampleTime: 随机取样,最后输出取样结果的分布,例如“99%的调用在xxx毫秒以内,99.99%的调用在xxx毫秒以内”
    (4).SingleShotTime: 以上模式都是默认一次 iteration 是 1s,唯有 SingleShotTime 是只运行一次。往往同时把 warmup 次数设为0,用于测试冷启动时的性能。

  • @Warmup(iterations = 3)
    Warmup是指在实际进行Benchmark前先进行预热的行为。因为JVM的JIT机制的存在,如果某个函数被调用多次以后,JVM会尝试将其编译成为机器码从而提高执行速度。所以为了让benchmark的结果更加接近真实情况就需要进行预热。

  • @Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS)
    Iteration是JMH进行测试的最小单位。大部分模式下,iteration代表的是一秒,JMH会在这一秒内不断调用需要benchmark的方法,然后根据模式对其采样,计算吞吐量,计算平均执行时间等。

  • @Threads(3)
    每个fork进程使用多少条线程去执行你的测试方法,默认值是Runtime.getRuntime().availableProcessors()。

  • @Fork(2)
    进行 fork 的次数。如果 fork 数是2的话,则 JMH 会 fork 出两个进程来进行测试。

  • @OutputTimeUnit(TimeUnit.MILLISECONDS)
    benchmark 结果所使用的时间单位,可用于类或者方法注解,使用java.util.concurrent.TimeUnit中的标准时间单位。

二使用

1.pom文件

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

2.测试代码
给要测试的代码都加上注解 @Benchmark

@BenchmarkMode(Mode.Throughput)
@Warmup(iterations = 3)
@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS)
@Threads(3)
@Fork(2)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class StringBuilderBenchmark {
 @Benchmark
 public void testStringAdd() {
     String a = "";
     for (int i = 0; i < 10; i++) {
         a += i;
     }
     print(a);
 }

 @Benchmark
 public void testStringBuilderAdd() {
     StringBuilder sb = new StringBuilder();
     for (int i = 0; i < 10; i++) {
         sb.append(i);
     }
     print(sb.toString());
 }

 private void print(String a) {
 }
}

3.main函数

public class Main {
    public static void main(String[] args) throws RunnerException {
        Options options = new OptionsBuilder()
                .include(StringBuilderBenchmark.class.getSimpleName())
                .output("/Users/aaa/bbb/jmhTest/Benchmark.log")
                .build();
        new Runner(options).run();
        System.out.println("ok");
    }
}

4.输出结果

#JMH version: 1.21
#VM version: JDK 11.0.4, OpenJDK 64-Bit Server VM, 11.0.4+10-b520.11
#VM invoker: /Applications/IntelliJ IDEA CE.app/Contents/jbr/Contents/Home/bin/java
#VM options: -javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=51147:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8
#Warmup: 3 iterations, 10 s each
#Measurement: 5 iterations, 5 s each
#Timeout: 10 min per iteration
#Threads: 3 threads, will synchronize iterations
#Benchmark mode: Throughput, ops/time
#Benchmark: com.jmh.StringBuilderBenchmark.testStringAdd
#Run progress: 0.00% complete, ETA 00:03:40
#Fork: 1 of 2
#Warmup Iteration 1: 21606.467 ops/ms
#Warmup Iteration 2: 21442.787 ops/ms
#Warmup Iteration 3: 23009.906 ops/ms
Iteration 1: 22378.146 ops/ms
Iteration 2: 21179.371 ops/ms
Iteration 3: 19842.664 ops/ms
Iteration 4: 21899.369 ops/ms
Iteration 5: 21295.508 ops/ms
#Run progress: 25.00% complete, ETA 00:02:48
#Fork: 2 of 2
#Warmup Iteration 1: 23853.829 ops/ms
#Warmup Iteration 2: 16675.787 ops/ms
#Warmup Iteration 3: 13181.383 ops/ms
Iteration 1: 18427.736 ops/ms
Iteration 2: 20586.554 ops/ms
Iteration 3: 17522.405 ops/ms
Iteration 4: 13306.951 ops/ms
Iteration 5: 16980.445 ops/ms

Result “com.jmh.StringBuilderBenchmark.testStringAdd”:
19341.915 ±(99.9%) 4243.255 ops/ms [Average]
(min, avg, max) = (13306.951, 19341.915, 22378.146), stdev = 2806.651
CI (99.9%): [15098.659, 23585.170] (assumes normal distribution)
#JMH version: 1.21
#VM version: JDK 11.0.4, OpenJDK 64-Bit Server VM, 11.0.4+10-b520.11
#VM invoker: /Applications/IntelliJ IDEA CE.app/Contents/jbr/Contents/Home/bin/java
#VM options: -javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=51147:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8
#Warmup: 3 iterations, 10 s each
#Measurement: 5 iterations, 5 s each
#Timeout: 10 min per iteration
#Threads: 3 threads, will synchronize iterations
#Benchmark mode: Throughput, ops/time
#Benchmark: com.jmh.StringBuilderBenchmark.testStringBuilderAdd
#Run progress: 50.00% complete, ETA 00:01:51
#Fork: 1 of 2
#Warmup Iteration 1: 65396.780 ops/ms
#Warmup Iteration 2: 56745.366 ops/ms
#Warmup Iteration 3: 58531.300 ops/ms
Iteration 1: 57888.256 ops/ms
Iteration 2: 58980.876 ops/ms
Iteration 3: 57263.057 ops/ms
Iteration 4: 57962.870 ops/ms
Iteration 5: 58125.756 ops/ms
#Run progress: 75.00% complete, ETA 00:00:55
#Fork: 2 of 2
#Warmup Iteration 1: 64354.645 ops/ms
#Warmup Iteration 2: 55955.423 ops/ms
#Warmup Iteration 3: 54001.690 ops/ms
Iteration 1: 47100.873 ops/ms
Iteration 2: 57030.425 ops/ms
Iteration 3: 58964.080 ops/ms
Iteration 4: 58772.270 ops/ms
Iteration 5: 56848.121 ops/ms

Result “com.jmh.StringBuilderBenchmark.testStringBuilderAdd”:
56893.658 ±(99.9%) 5330.442 ops/ms [Average]
(min, avg, max) = (47100.873, 56893.658, 58980.876), stdev = 3525.757
CI (99.9%): [51563.216, 62224.101] (assumes normal distribution)
#Run complete. Total time: 00:03:43
REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on
why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial
experiments, perform baseline and negative tests that provide experimental control, make sure
the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts.
Do not assume the numbers tell you what you want them to tell.

Benchmark Mode Cnt Score Error Units
StringBuilderBenchmark.testStringAdd thrpt 10 19341.915 ± 4243.255 ops/ms
StringBuilderBenchmark.testStringBuilderAdd thrpt 10 56893.658 ± 5330.442 ops/ms

参考:https://blog.csdn.net/feeltouch/article/details/83353557
https://cloud.tencent.com/developer/article/1502528

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值