文章目录
参考资料:
【基准测试】JMH 简单入门
JMH 微基准测试套件
JAVA拾遗 — JMH与8个测试陷阱
深入拆解Java 虚拟机 - 29 | 基准测试框架JMH(下)
一、Jmh基准测试介绍
1. 基准测试
基准测试(benchmarking)是一种测量和评估软件性能指标的活动。你可以在某个时候通过基准测试建立一个已知的性能水平(称为基准线),当系统的软硬件环境发生变化之后再进行一次基准测试以确定那些变化对性能的影响。这是基准测试最常见的用途。其他用途包括测定某种负载水平下的性能极限、管理系统或环境的变化、发现可能导致性能问题的条件,等等。
JMH使用OPS来表示吞吐量,OPS,Opeartion Per Second,是衡量性能的重要指标,指得是每秒操作量。数值越大,性能越好。类似的概念还有TPS,表示每秒的事务完成量,QPS,每秒的查询量。
JMH,即Java Microbenchmark Harness,是专门用于代码微基准测试的工具套件。主要是基于方法层面的基准测试,精度可以达到纳秒级。当你定位到热点方法,希望进一步优化方法性能的时候,就可以使用JMH对优化的结果进行量化的分析。
2. 导入依赖
<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>
3. 编写测试代码
运行测试的入口
public class StringBuilderRunner {
public static void main( String[] args ) throws RunnerException {
Options opt = new OptionsBuilder()
// 导入要测试的类
.include(StringConnectBenchmark.class.getSimpleName())
// 预热5轮
.warmupIterations(5)
// 度量10轮
.measurementIterations(10)
.mode(Mode.Throughput)
.forks(3)
.build();
new Runner(opt).run();
}
}
StringBuilderRunner
这个 runner 类的作用,就是启动基准测试。
JMH 通常有两种方式启动,一种就是通过命令行使用 maven 命令执行。这种适合对于大型基准测试,像那些要运行很多很多次,并且运行的时间也很长的情况下。你可以直接打个 jar包,发到服务器上,敲个命令就不用管它,过几十分钟、几小时、几天的时间再回来看结果。
但是很多情况下,我们只是想简单测试一个小功能,没必要还要搞台服务器去跑。所以 JMH 还提供了一种通过 Main方法运行的方式,就如上面代码所示。
被测方法
public class StringConnectBenchmark {
@Benchmark
public void testStringBuilder() {
print(new StringBuilder().append(1).append(2).append(3).toString());
}
@Benchmark
public void testStringAdd() {
print(new String() + 1 + 2 + 3);
}
@Benchmark
public void testStringConcat() {
print(new String().concat("1").concat("2").concat("3"));
}
@Benchmark
public void testStringBuffer() {
print(new StringBuffer().append(1).append(2).append(3).toString());
}
@Benchmark
public void testStringFormat() {
print(String.format("%s%s%s", 1, 2, 3));
}
private void print(String toString) {
}
}
StringConnectBenchmark
这个就是真正执行基准测试的类,这个类很像单元测试的类,每个测试方法中写上你要执行的测试代码。只不过这里把@Test换成了@Benchmark注解。
而加上了这个就指明这个方法是基准测试方法,当 Runner类的 Main方法运行时,它就会找这些被注解修饰的方法,再按指定的规则去进行基准测试。当然可能不同的方法有时候需要不同的规则,这个时间可以通过上面方法对应的注解形式去单独指定某个方法的规则即可。
运行结果
# JMH version: 1.19
# VM version: JDK 11.0.5, VM 11.0.5+10-b520.38
# VM invoker: D:\Program Files\JetBrains\IntelliJ IDEA 2019.3.3\jbr\bin\java.exe
# VM options