Loading... # JMH测试工具入门 ## 什么是JMH > 官网: http://openjdk.java.net/projects/code-tools/jmh/ ## 创建JMH测试 1. maven依赖 ``` <!-- https://mvnrepository.com/artifact/org.openjdk.jmh/jmh-core --> <dependency> <groupId>org.openjdk.jmh</groupId> <artifactId>jmh-core</artifactId> <version>1.21</version> </dependency> <!-- https://mvnrepository.com/artifact/org.openjdk.jmh/jmh-generator-annprocess --> <dependency> <groupId>org.openjdk.jmh</groupId> <artifactId>jmh-generator-annprocess</artifactId> <version>1.21</version> <scope>test</scope> </dependency> ``` 2. idea安装JMH插件 JMH plugin v1.0.3 3. 由于用到了注解,打开运行程序注解配置 compiler -> Annotation Processors -> Enable Annotation Processing 4. 定义需要测试类PS (ParallelStream) ``` 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; } } ``` 5. 写单元测试 这个测试类一定要在test package下面 ``` public class PSTest { @Benchmark public void testForEach() { PS.foreach(); } } ``` 6. 运行测试类,如果遇到下面的错误: ``` 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 7. 阅读测试报告 ## JMH中的注解 ### @Warmup 预热,由于JVM中对于特定代码会存在优化(本地化),预热对于测试结果很重要 - iterations:预热的次数。 - time:每次预热的时间。 - timeUnit:时间的单位,默认秒。 - batchSize:批处理大小,每次操作调用几次方法。 ### @Measurement 度量,其实就是一些基本的测试参数。 - iterations 进行测试的轮次 - time 每轮进行的时长 - timeUnit 时长单位 ### @BenchmarkMode 基准测试类型。 - Throughput: 整体吞吐量,例如“1秒内可以执行多少次调用”。 - AverageTime: 调用的平均时间,例如“每次调用平均耗时xxx毫秒”。 - SampleTime: 随机取样,最后输出取样结果的分布,例如“99%的调用在xxx毫秒以内,99.99%的调用在xxx毫秒以内” - SingleShotTime: 以上模式都是默认一次 iteration 是 1s,唯有 SingleShotTime 是只运行一次。往往同时把 warmup 次数设为0,用于测试冷启动时的性能。 - All(“all”, “All benchmark modes”); ### @Fork 进行 fork 的次数。可用于类或者方法上。如果 fork 数是2的话,则 JMH 会 fork 出两个进程来进行测试。 ### @Threads 每个进程中的测试线程,可用于类或者方法上。一般选择为cpu乘以2。如果配置了 Threads.MAX ,代表使用 Runtime.getRuntime().availableProcessors() 个线程。 ### @Benchmark 方法级注解,表示该方法是需要进行 benchmark 的对象,用法和 JUnit 的 @Test 类似。 ## Next 官方样例: http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/ Last modification:November 27th, 2020 at 06:31 pm © 允许规范转载