JMH(Java基准测试工具套件)入门 官网 http://openjdk.java.net/projects/code-tools/jmh/
创建JMH测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 <?xml version="1.0" encoding="UTF-8"?> <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <properties > <project.build.sourceEncoding > UTF-8</project.build.sourceEncoding > <encoding > UTF-8</encoding > <java.version > 1.8</java.version > <maven.compiler.source > 1.8</maven.compiler.source > <maven.compiler.target > 1.8</maven.compiler.target > </properties > <groupId > mashibing.com</groupId > <artifactId > HelloJMH2</artifactId > <version > 1.0-SNAPSHOT</version > <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 > test</scope > </dependency > </dependencies > </project >
IDEA安装JMH插件 JMH plugin v1.0.3
由于用到了注解,打开运行程序注解配置
compiler -> Annotation Processors -> Enable Annotation Processing
定义需要测试类PS (ParallelStream)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.util.ArrayList;import java.util.List;import java.util.Random;public class PS { static List<Integer> nums = new ArrayList<>(); static { Random r = new Random(); for (int i = 0 ; i < 10000 ; i++) nums.add(1000000 + r.nextInt(1000000 )); } static void foreach () { nums.forEach(v->isPrime(v)); } static void parallel () { nums.parallelStream().forEach(PS::isPrime); } static boolean isPrime (int num) { for (int i=2 ; i<=num/2 ; i++) { if (num % i == 0 ) return false ; } return true ; } }
这段代码一定要写在test package下
1 2 3 4 5 6 7 8 9 10 11 import org.openjdk.jmh.annotations.Benchmark;import static org.junit.jupiter.api.Assertions.*;public class PSTest { @Benchmark public void testForEach () { PS.foreach(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.wangwren.jmh;import org.openjdk.jmh.annotations.*;public class TestPS { @Benchmark @Warmup (iterations = 1 ,time = 3 ) @Fork (5 ) @BenchmarkMode (Mode.Throughput) @Measurement (iterations = 1 , time = 3 ) public void testForEach () { PS.parallel(); } }
运行测试类,如果是Windows系统可能会遇到下面的错误:
1 2 3 ERROR: org.openjdk.jmh.runner.RunnerException: ERROR: Exception while trying to acquire the JMH lock (C:\WINDOWS\/jmh.lock): C:\WINDOWS\jmh.lock (拒绝访问。), exiting. Use -Djmh.ignoreLock=true to forcefully continue. at org.openjdk.jmh.runner.Runner.run(Runner.java:216) at org.openjdk.jmh.Main.main(Main.java:71)
这个错误是因为JMH运行需要访问系统的TMP目录,解决办法是:
打开RunConfiguration -> Environment Variables -> include system environment viables
我使用的是Mac系统,没有出现这种错误。
阅读测试报告
测试结果:
JMH的基本概念
Warmup 预热,由于JVM中对于特定代码会存在优化(本地化),预热对于测试结果很重要
@warmup(iterations = 1,time = 3)
在JVM启动的时候调用 1 次(也可以调用多次),即预热多少次,每次多少秒,这里指定的就是预热1次,每次3秒。(线程之间间隔3秒)
Mesurement 总共执行多少次测试
Timeout,默认每次迭代在10分钟之内完成,完不成就是超时了。
Threads 线程数,由fork指定,@Fork(5)
,指定5个线程测试。
BenchmarkMode 基准测试的模式,@BenchmarkMode(Mode.Throughput)
,基准测试的模式,用的最多的就是Mode.Throughput,表示吞吐量(一秒能执行多少次) ,(还有好多其他的)
Benchmark 测试哪一段代码,如果只写了这一个注解,默认会执行10秒。
Measurement,@Measurement(iterations = 1,time = 3)
,整个测试测试多少遍,一般设置的比较长。
每个线程里面执行一次Warmup,调用一次方法。
Next 官方样例