51Testing软件测试论坛
标题:
基于JMH微基准测试入门案例
[打印本页]
作者:
草帽路飞UU
时间:
2022-8-8 15:31
标题:
基于JMH微基准测试入门案例
本帖最后由 草帽路飞UU 于 2022-8-12 15:48 编辑
JMH - java Microbenchmark Harness
微基准测试,他是测试某个方法的性能到底是好还是不好。 这个测试框架是2013年发出来的,有JLT开发人员开发,后来归到OpenJDK下面。
下面介绍什么是JMH,他是用来干什么的,怎么使用?基于idea中使用。
创建JMH测试
1.创建maven项目,添加依赖
jmh-core (jmh的核心) 1.2 mh-generator-annprocess(注解处理包)。
<!--jmh依赖-->
<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>
2.idea安装JMH插件JMH plugin
File->Settings->lugins->JMH plugin。
[attach]140705[/attach]
3. 打开运行程序注解配置
因为JMH在运行的时候他用到了注解,注解这个东西你自己得写一个程序得解释他,所以你要把这个给设置上允许JMH能够对注解进行处理: Compiler -> Annotation Processors -> Enable Annotation Processing(打钩)。
[attach]140706[/attach]
4. 定义需要测试类
看这里,写了一个类,并行处理流的一个程序,定义了一个list集合,然后往这个集合里扔了1000个数。
写了一个方法来判断这个数到底是不是一个质数。 写了两个方法,第一个是用forEach来判断我们这1000个数里到底有谁是质数;第二个是使用了并行处理流。 这个forEach的方法就只有单线程里面执行,挨着从头拿到尾,从0拿到1000,但是并行处理的时候会有多个线程采用ForkJoin的方式来把里面的数分成好几份并行的尽兴处理。一种是串行处理,一种是并行处理,都可以对他们进行测试,但需要注意这个基准测试并不是对比测试的,你只是侧试一下你这方法写出这样的情况下他的吞吐量到底是多少,这是一个非常专业的测试的工具。严格的来讲这部分是测试开发专业的。
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Jmh {
static List<Integer> nums = new ArrayList<>();
static {
Random r = new Random();
for (int i = 0; i < 10000; i++) {
nums.add(1000000 + r.nextInt(1000000));
}
}
public static void foreach() {
nums.forEach(v -> isPrime(v));
}
static void parallel() {
nums.parallelStream().forEach(Jmh::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下面.
我对这个方法进行测试testForEach,很简单我就调用Jmh这个类的foreach就行了,对它测试 最关键的是我加了这个注解@Benchmark,这个是JMH的注解,是要被JMH来解析处理的, 这也是我们为什么要把那个Annotation Processing给设置上的原因,非常简单, 你只要加上注解就可以对这个方法进行微基准测试了,点击右键直接run.
import org.openjdk.jmh.annotations.*;
public class JmhTest {
@Benchmark
@Warmup(iterations = 1, time = 3)//在专业测试里面首先要进行预热,预热多少次,预热多少时间
@Fork(5)//意思是用多少个线程去执行我们的程序
@BenchmarkMode(Mode.Throughput)//是对基准测试的一个模式,这个模式用的最多的是Throughput吞吐量
@Measurement(iterations = 1, time = 3)//是整个测试要测试多少遍,调用这个方法要调用多少次
public void testForEach() {
Jmh.foreach();
}
}
[attach]140707[/attach]
6. 运行测试类,如果遇到下面的错误
ERROR: org.openjdk.jmh.runner.RunnerException: ERROR: Exception while trying to acquire the 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)
[attach]140708[/attach]
这个错误是因为JMH运行需要访问系统的TMP目录,解决办法是: 打开Run Configuration -> Environment Variables -> include system environment viables(勾选)在这里插入图片描述最后结果:
[attach]140709[/attach]
JMH中的基本概念
Warmup
预热,由于JVM中对于特定代码会存在优化(本地化),预热对于测试结果很重要 2. Mesurement 总共执行多少次测试 3. Timeout 4. Threads 线程数,由fork指定 5. Benchmark mode 基准测试的模式 6. Benchmark 测试哪一段代码。
这个是JMH的一个入门,严格来讲这个和我们的关系其实并不大,这个是测试部门干的事儿,但是你了解一下没有特别多的坏处,你也知道你的方法最后效率高或者底,可以通过一个简单的JMH插件来帮你 完成,你不要在手动的去写这件事儿了。 如果说大家对JMH有兴趣,你们在工作中可能会有用的上大家去读一下官方的例子,官方大概有好几十 个例子程序,你可以自己一个一个的去研究。
欢迎光临 51Testing软件测试论坛 (http://bbs.51testing.com/)
Powered by Discuz! X3.2