什么是 JMH

JMH 是 Java Microbenchmark Harness 的缩写。中文意思大致是 “JAVA 微基准测试套件”。首先先明白什么是“基准测试”。百度百科给的定义如下:

①、可重复性:可进行重复性的测试,这样做有利于比较每次的测试结果,得到性能结果的长期变化趋势,为系统调优和上线前的容量规划做参考。

②、可观测性:通过全方位的监控(包括测试开始到结束,执行机、服务器、数据库),及时了解和分析测试过程发生了什么。

③、可展示性:相关人员可以直观明了的了解测试结果(web界面、仪表盘、折线图树状图等形式)。

④、真实性:测试的结果反映了客户体验到的真实的情况(真实准确的业务场景+与生产一致的配置+合理正确的测试方法)。

⑤、可执行性:相关人员可以快速的进行测试验证修改调优(可定位可分析)。

可见要做一次符合特质的基准测试,是很繁琐也很困难的。外界因素很容易影响到最终的测试结果。特别对于 JAVA的基准测试。


有些文章会告诉我们 JAVA是 C++编写的,一般来说 JAVA编写的程序不太可能比 C++编写的代码运行效率更好。但是JAVA在某些场景的确要比 C++运行的更高效。不要觉得天方夜谭。其实 JVM随着这些年的发展已经变得很智能,它会在运行期间不断的去优化。


这对于我们程序来说是好事,但是对于性能测试就头疼的。你运行的次数与时间不同可能获得的结果也不同,很难获得一个比较稳定的结果。对于这种情况,有一个解决办法就是大量的重复调用,并且在真正测试前还要进行一定的预热,使结果尽可能的准确。

除了这些,对于结果我们还需要一个很好的展示,可以让我们通过这些展示结果判断性能的好坏。

而这些JMH都有!😊

如何使用 JMH

下面我们以字符串拼接的几种方法为例子使用JMH做基准测试。

1. 导入依赖

JMH是 JDK9自带的,如果你是 JDK9 之前的版本也可以通过导入 openjdk

<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> </dependency>

2. 目录结构

. ├── pom.xml └── src    ├── main    │  └── java    │     └── cn    │        └── coder4j    │           └── study    │              └── demo    │                 └── jmh    │                    ├── benchmark    │                    │  └── StringConnectBenchmark.java    │                    └── runner    │                       └── StringBuilderRunner.java    └── test       └── java          └── cn             └── coder4j                └── study                   └── demo

3. 具体代码

  • StringBuilderRunner.java
/**  * coder4j.cn  * Copyright (C) 2013-2018 All Rights Reserved.  */ package cn.coder4j.study.demo.jmh.runner;  import cn.coder4j.study.demo.jmh.benchmark.StringConnectBenchmark; import org.openjdk.jmh.annotations.Mode; 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;  /**  * @author buhao  * @version StringBuilderRunner.java, v 0.1 2018-12-25 09:53 buhao  */ public class StringBuilderRunner {      public static void main( String[] args ) throws RunnerException {         Options opt = new OptionsBuilder()                 // 导入要测试的类                 .include(StringConnectBenchmark.class.getSimpleName())                 // 预热5轮                 .warmupIterations(5)