如何使用 JMH 进行 Java 基准性能测试(benchmarking)
本文介绍了如何使用 Java Microbenchmark Harness(JMH) 来测试 Java 代码的基准性能。 基本上就是官方 README.md (https://github.com/openjdk/jmh) 的精简翻译。
Java Microbenchmark Harness(JMH) 是一款用来构建、运行和分析 Java (或其他基于JVM)代码性能的测试工具。 JMH 支持 nano/micro/milli/macro 等精度的性能测试。其执行结果会助你更好地理解自己的代码性能,在性能调优的时候更有科学依据。
概览
JMH 提供了 @Benchmark 和其他与测试相关的一系列注解。开发者可以跟写 unit test 一样编写性能测试用例。
public class MyBenchmark {
@Benchmark
@Warmup(iterations = 1)
@Fork(1)
@Measurement(iterations = 1, time = 1, timeUnit = TimeUnit.MINUTES)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public void UUID() {
UUID.randomUUID();
}
}
测试的结果如下方日志所示。
/Users/myname/workspace/jdk/build/macosx-x86_64-server-release/jdk/bin/java -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=62626:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/myname/workspace/hellojmh/target/classes:/Users/myname/.m2/repository/org/openjdk/jmh/jmh-core/1.29/jmh-core-1.29.jar:/Users/myname/.m2/repository/net/sf/jopt-simple/jopt-simple/4.6/jopt-simple-4.6.jar:/Users/myname/.m2/repository/org/apache/commons/commons-math3/3.2/commons-math3-3.2.jar org.openjdk.jmh.Main me.imlc.MyBenchmark.*
# JMH version: 1.29
# VM version: JDK 17-internal, OpenJDK 64-Bit Server VM, 17-internal+0-adhoc.myname.jdk
# VM invoker: /Users/myname/workspace/jdk/build/macosx-x86_64-server-release/jdk/bin/java
# VM options: -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=62626:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8
# Blackhole mode: full + dont-inline hint
# Warmup: 1 iterations, 10 s each
# Measurement: 1 iterations, 1 min each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: me.imlc.MyBenchmark.UUID
# Run progress: 0.00% complete, ETA 00:01:10
# Fork: 1 of 1
# Warmup Iteration 1: 0.004 ops/ns
Iteration 1: 0.005 ops/ns
Result "me.imlc.MyBenchmark.UUID":
0.005 ops/ns
# Run complete. Total time: 00:01:11
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
MyBenchmark.UUID thrpt 0.005 ops/ns
诚如上方 REMEMBER 所言,性能测试的结果受各种情况影响,切记不要盲目相信测试结果。
如何使用 JMH
在 JMH 的 README.md 中,官方推荐以命令行的方式使用 JMH。简而言之,把代码构建成 jar,然后 java -jar <...>.jar
执行。
初次接触 JMH,可以使用 Maven archetype 生成 Maven 项目。
- 官方文档中的示例代码没有指定
-DarchetypeVersion=1.29
。默认生成的 JMH 项目,支持的 JDK 版本, Maven 插件的版本和使用方式都太旧。为确保你能以最新的模板生成项目,请到 https://repo.maven.apache.org/maven2/org/openjdk/jmh/jmh-java-benchmark-archetype/ 检查最新的版本号 2. 你可以在上方地址看到其他的 archetypes。例如 Groovy、Kotlin 或者 Scale。如需测试其他代码,修改
-DarchetypeArtifactId=jmh-java-benchmark-archetype
即可。
mvn archetype:generate \
-DinteractiveMode=false \
-DarchetypeGroupId=org.openjdk.jmh \
-DarchetypeArtifactId=jmh-java-benchmark-archetype \
-DarchetypeVersion=1.29 \
-DgroupId=org.sample \
-DartifactId=test \
-Dversion=1.0
上方命令执行完成后,你会在当前目录找到一个刚生成的新鲜热辣的 test
文件夹。简而言之,它就是一个普通的 Maven 项目。
项目里的 src/main/java/org/sample/MyBenchmark.java
为生成的测试用例文件。你可以直接在该文件中添加你要测试的代码。
然后,
cd test/
mvn clean verify
java -jar target/benchmarks.jar
通过 Maven 构建 jar 包,然后执行,略等片刻,你就可以看到基准性能测试的结果。
附加 "-h" 参数,你可以看到可用的命令行参数:
java -jar target/benchmarks.jar -h