在多线程中有这样一个思想,就是尽可能的压榨cpu,这里就提到了效率。那么怎么知道一个程序的效率呢,JMH(java Microbenchmark Harness),就是专门测量方法性能好不好的一个工具。有时我们想测试自己写的代码的性能,就不用自己写测试代码,而可以直接用它了。本篇就对其做一个简单的介绍。
JMH使用步骤这里会做一个小实验,测算不同方法的吞吐量,也是对JMH做一个简单的入门。
-
创建Maven项目,添加两个依赖:
1.1:jmh-core (jmh的核心)
1.2:jmh-generator-annprocess(注解处理包)
org.openjdk.jmh jmh-core 1.21 org.openjdk.jmh jmh-generator-annprocess 1.21 test -
idea安装JMH插件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nfWXJ9r5-1651679078535)(C:Users27901AppDataRoamingTyporatypora-user-imagesimage-20220502123707707.png)]
-
由于用到了注解,打开运行程序注解配置
compiler -> Annotation Processors -> Enable Annotation Processing
-
定义需要测试类PS (ParallelStream)
在这个类中,并行处理流的一个程序,定义了一个list集合,然后往这个集合里扔了1000个数。写了一个方法来判断这个数到底是不是一个质数。写了两个方法,第一个是用forEach来判断我们这1000个数里到底有谁是质数;第二个是使用了并行处理流,这个forEach的方法就只有单线程里面执行,挨着从头拿到尾,从0拿到1000,但是并行处理的时候会有多个线程采用ForkJoin的方式来把里面的数分成好几份并行的尽兴处理。一种是串行处理,一种是并行处理,对这两个方法进行性能测试。
public class PS { static Listnums = 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下面
我对这个方法进行测试testForEach,很简单我就调用PS这个类的foreach就行了,对它测试最关键的是我加了这个注解@Benchmark,这个是JMH的注解,是要被JMH来解析处理的,这也是我们为么要把那个Annotation Processing给设置上的原因,非常简单,你只要加上注解就可以对这个方法进行微基准测试了,点击右键直接run。
public class PSTest { @Benchmark @Fork(5)//意思是用多少个线程去执行我们的程序 @BenchmarkMode(Mode.Throughput)//是对基准测试的一个模式,这个模式用的最多的是Throughput吞吐量 @Measurement(iterations=1, time=3)//是整个测试要测试多少遍,调用这个方法要调用多少次 public void testForEach() { // PS.foreach(); PS.parallel(); } } -
Run配置,运行访问环境变量。
RunConfiguration -> Environment Variables -> include system environment viables
-
测试结果
foreach方法,可以看到其每秒能执行0.768 ± 0.010次
Benchmark Mode Cnt Score Error Units PSTest.testForEach thrpt 25 0.768 ± 0.010 ops/s
parallel方法,可以看到其每秒能执行5.885 ± 1.483次
Benchmark Mode Cnt Score Error Units PSTest.testForEach thrpt 5 5.885 ± 1.483 ops/s
- Warmup
预热,由于JVM中对于特定代码会存在优化(本地化),预热对于测试结果很重要 - Mesurement
总共执行多少次测试 - Threads
线程数,由fork指定 - Benchmark mode
基准测试的模式 - Benchmark
测试哪一段代码
本文是用JMH对一个方法的吞吐量进行了性能测试,作为JMH的入门例子。实际JMH还有很多用法,进一步探索可以去看官方的例子。
官方样例:
http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/



