JMH只适合细粒度的方法测试,并不适用于系统之间的链路测试
JMH官方推荐使用Maven来搭建基准测试的骨架,使用也很简单,使用如下命令来生成maven项目:
mvn archetype:generate -DinteractiveMode=false -DarchetypeGroupId=org.openjdk.jmh -DarchetypeArtifactId=jmh-java-benchmark-archetype -DgroupId=org.sample -DartifactId=jmh-benchmark -Dversion=1.0
上面的maven命令使用了jmh-java-benchmark-archetype来生成java语言的基准测试骨架,如果使用其他语言可以将这个参数对应替换,所有可选参数参考jmh,生成的项目groupId是org.sample,artifaceId是test,执行完之后会在当前目录下生成一个test目录,切换到test目录下执行
mvn clean install
就会生成benchmarks.jar,再使用java -jar benchmarks.jar
就可以执行基准测试了。
如果你想直接在已有maven项目中集成JMH,那也很简单,手动在POM文件中添加以下两个依赖就行了,
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.26</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.26</version>
<scope>provided</scope>
</dependency>
从maven archetype插件生成的pom文件来看,这个工程使用了maven-shade-plugin来将所有的依赖打包到同一个jar包中,并在Manifest文件中配置了Main-Class属性,这样就能直接通过java -jar命令来执行了。
@Benchmark标签是用来标记测试方法的,只有被这个注解标记的话,该方法才会参与基准测试,但是有一个基本的原则就是被@Benchmark标记的方法必须是public的。
@Warmup用来配置预热的内容,可用于类或者方法上,越靠近执行方法的地方越准确。一般配置warmup的参数有这些:
用来控制实际执行的内容,配置的选项本warmup一样。
@BenchmarkMode主要是表示测量的纬度,有以下这些纬度可供选择:
@OutputTimeUnit代表测量的单位,比如秒级别,毫秒级别,微妙级别等等。一般都使用微妙和毫秒级别的稍微多一点。该注解可以用在方法级别和类级别,当用在类级别的时候会被更加精确的方法级别的注解覆盖,原则就是离目标更近的注解更容易生效。
在很多时候我们需要维护一些状态内容,比如在多线程的时候我们会维护一个共享的状态,这个状态值可能会在每隔线程中都一样,也有可能是每个线程都有自己的状态,JMH为我们提供了状态的支持。该注解只能用来标注在类上,因为类作为一个属性的载体。 @State的状态值主要有以下几种:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
/**
* @copyright: Copyright (c) 2020
* @company: 上海汇石数字科技有限公司
* @description:
* @author: Qi.Hong
* @create: 2020-10-13 12:15
*/
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
public class CollectionsTest {
private static final int TEN_MILLION = 10000000;
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void arrayList() {
List<String> array = new ArrayList<>();
for (int i = 0; i < TEN_MILLION; i++) {
array.add("123");
}
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void arrayListSize() {
List<String> array = new ArrayList<>(TEN_MILLION);
for (int i = 0; i < TEN_MILLION; i++) {
array.add("123");
}
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(CollectionsTest.class.getSimpleName())
.forks(1)
.build();
new Runner(opt).run();
}
}
输出:
# JMH version: 1.26
# VM version: JDK 1.8.0_261, Java HotSpot(TM) 64-Bit Server VM, 25.261-b12
# VM invoker: D:\Scoop\apps\oraclejdk8\current\jre\bin\java.exe
# VM options: -javaagent:D:\Program Files (x86)\JetBrains\IntelliJ IDEA\lib\idea_rt.jar=2510:D:\Program Files (x86)\JetBrains\IntelliJ IDEA\bin -Dfile.encoding=UTF-8
# Warmup: 5 iterations, 1 s each
# Measurement: 5 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Average time, time/op
# Benchmark: org.sample.CollectionsTest.arrayList
# Run progress: 0.00% complete, ETA 00:00:20
# Fork: 1 of 1
# Warmup Iteration 1: 98276.345 us/op
# Warmup Iteration 2: 78334.454 us/op
# Warmup Iteration 3: 60003.018 us/op
# Warmup Iteration 4: 69836.653 us/op
# Warmup Iteration 5: 56462.906 us/op
Iteration 1: 55989.247 us/op
Iteration 2: 57849.294 us/op
Iteration 3: 54504.816 us/op
Iteration 4: 55541.316 us/op
Iteration 5: 56276.563 us/op
Result "org.sample.CollectionsTest.arrayList":
56032.247 ±(99.9%) 4691.335 us/op [Average]
(min, avg, max) = (54504.816, 56032.247, 57849.294), stdev = 1218.325
CI (99.9%): [51340.913, 60723.582] (assumes normal distribution)
# JMH version: 1.26
# VM version: JDK 1.8.0_261, Java HotSpot(TM) 64-Bit Server VM, 25.261-b12
# VM invoker: D:\Scoop\apps\oraclejdk8\current\jre\bin\java.exe
# VM options: -javaagent:D:\Program Files (x86)\JetBrains\IntelliJ IDEA\lib\idea_rt.jar=2510:D:\Program Files (x86)\JetBrains\IntelliJ IDEA\bin -Dfile.encoding=UTF-8
# Warmup: 5 iterations, 1 s each
# Measurement: 5 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Average time, time/op
# Benchmark: org.sample.CollectionsTest.arrayListSize
# Run progress: 50.00% complete, ETA 00:00:13
# Fork: 1 of 1
# Warmup Iteration 1: 37526.226 us/op
# Warmup Iteration 2: 36804.161 us/op
# Warmup Iteration 3: 91434.682 us/op
# Warmup Iteration 4: 465368.225 us/op
# Warmup Iteration 5: 206318.400 us/op
Iteration 1: 207185.940 us/op
Iteration 2: 168980.250 us/op
Iteration 3: 103344.225 us/op
Iteration 4: 34195.040 us/op
Iteration 5: 34570.855 us/op
Result "org.sample.CollectionsTest.arrayListSize":
109655.262 ±(99.9%) 300766.041 us/op [Average]
(min, avg, max) = (34195.040, 109655.262, 207185.940), stdev = 78107.986
CI (99.9%): [≈ 0, 410421.303] (assumes normal distribution)
# Run complete. Total time: 00:00:27
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
CollectionsTest.arrayList avgt 5 56032.247 ± 4691.335 us/op
CollectionsTest.arrayListSize avgt 5 109655.262 ± 300766.041 us/op
Process finished with exit code 0
原文:https://www.cnblogs.com/hongdada/p/13809962.html