JMH基准测试

一、基准测试

  • 基准测试是什么

    • 基准测试是指通过设计科学的测试方法、测试工具和测试系统,实现对一类测试对象的某项性能指标进行定量的和可对比的测试。

    • 例如,对计算机CPU进行浮点运算、数据访问的带宽和延迟等指标的基准测试,可以使用户清楚地了解每一款CPU的运算性能及作业吞吐能力是否满足应用程序的要求

    • 再如对数据库管理系统的ACID(Atomicity, Consistency, Isolation, Durability, 原子性、一致性、独立性和持久性)、查询时间和联机事务处理能力等方面的性能指标进行基准测试,也有助于使用者挑选最符合自己需求的数据库系统

  • 通过基准测试,我们可以了解某个软件在给定环境下的性能表现,对使用者而言可以用作选型的参考,对开发者而言可以作为后续改进的基本参照。

二、JMH

  • JMH是什么

    • JMH 是一个面向 Java 语言或者其他 Java 虚拟机语言的性能基准测试框架。

    • 它针对的是纳秒级别、微秒级别、毫秒级别,以及秒级别的性能测试。

    • 该工具由open JDK提供并维护,测试结果可信度较高,该项目官方还在持续更新中。

    • 官网

    • 详解36个官方例子

三、入门

  • 因为 JMH 是 JDK9 之后才自带的,如果是 JDK9 之前的版本需要加入如下依赖

 
     org.openjdk.jmh
     jmh-core
     1.32
 
 
     org.openjdk.jmh
     jmh-generator-annprocess
     1.32
 

3.1 第一个例子:Hello JMH

 import org.openjdk.jmh.annotations.Benchmark;
 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 Example_01_HelloJMH {
 ​
     @Benchmark
     public String sayHello() {
         return "HELLO JMH!";
     }
 ​
     public static void main(String[] args) throws RunnerException {
         Options options = new OptionsBuilder()
                 .include(Example_01_HelloJMH.class.getSimpleName())
                 .forks(1)
                 .build();
         new Runner(options).run();
     }
 }

3.2 运行结果

 # JMH version: 1.32
 # VM version: JDK 1.8.0_241, Java HotSpot(TM) 64-Bit Server VM, 25.241-b07
 # VM invoker: G:\Java\jdk1.8.0_241\jre\bin\java.exe
 # VM options: -javaagent:G:\JetBrains\IntelliJ IDEA 2020.2.3\lib\idea_rt.jar=56180:G:\JetBrains\IntelliJ IDEA 2020.2.3\bin -Dfile.encoding=UTF-8
 # Blackhole mode: full + dont-inline hint
 # 预热配置
 # Warmup: 5 iterations, 10 s each
 # 检测配置
 # Measurement: 5 iterations, 10 s each
 # 超时配置
 # Timeout: 10 min per iteration
 # 测试线程配置
 # Threads: 1 thread, will synchronize iterations
 # 基准测试运行模式
 # Benchmark mode: Throughput, ops/time
 # 当前测试的方法
 # Benchmark: com.ziroom.test.Example_01_HelloJMH.sayHello
 ​
 # 运行过程的输出
 # Run progress: 0.00% complete, ETA 00:01:40
 # Fork: 1 of 1
 # Warmup Iteration   1: 2924740803.993 ops/s
 # Warmup Iteration   2: 2916472711.387 ops/s
 # Warmup Iteration   3: 3024204715.897 ops/s
 # Warmup Iteration   4: 3051723946.668 ops/s
 # Warmup Iteration   5: 2924014544.301 ops/s
 Iteration   1: 2909665054.710 ops/s
 Iteration   2: 2989675862.826 ops/s
 Iteration   3: 2965046292.629 ops/s
 Iteration   4: 3020263765.220 ops/s
 Iteration   5: 2929485177.735 ops/s
 ​
 # 当前方法测试结束的报告
 Result "com.ziroom.test.Example_01_HelloJMH.sayHello":
   2962827230.624 ±(99.9%) 171803440.922 ops/s [Average]
   (min, avg, max) = (2909665054.710, 2962827230.624, 3020263765.220), stdev = 44616808.022
   CI (99.9%): [2791023789.702, 3134630671.547] (assumes normal distribution)
 ​
 ​
 # Run complete. Total time: 00:01:41
 ​
 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跑完后的最终报告
 Benchmark                     Mode   Cnt           Score           Error  Units
 Example_01_HelloJMH.sayHello  thrpt    5  2962827230.624 ± 171803440.922  ops/s

3.3 使用 JMH 测试 Spring/SpringBoot

 import com.spadesk.springbootjmhtest.controller.TestController;
 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 org.springframework.boot.SpringApplication;
 import org.springframework.context.ConfigurableApplicationContext;
 import java.util.concurrent.TimeUnit;
 ​
 @BenchmarkMode(Mode.AverageTime)
 @OutputTimeUnit(TimeUnit.MILLISECONDS)
 @State(Scope.Benchmark)
 public class SpringBootBenchMark {
     
     public static void main(String[] args) throws RunnerException {
         Options options = new OptionsBuilder()
                 .include(SpringBootBenchMark.class.getSimpleName())
                 .warmupIterations(3)
            

你可能感兴趣的:(java)