OpenJDK 中的开源项目 JMH(Java Microbenchmark Harness)。JMH 是一个面向 Java 语言或者其他 Java 虚拟机语言的性能基准测试框架。它针对的是纳秒级别、微秒级别、毫秒级别,以及秒级别的性能测试。
如何使用
- 根据maven 上的 archetype,生成项目骨架
mvn archetype:generate -DinteractiveMode=false -DarchetypeGroupId=org.openjdk.jmh -DarchetypeArtifactId=jmh-java-benchmark-archetype -DgroupId=org.sample -DartifactId=JMHTest -Dversion=1.21
将生成后的代码导入到你使用的IDE里,生成的代码结构如下:
JMH archetype生成的项结构
- 编写需要进行基准测试的逻辑。代码如下:
package org.sample;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Threads;
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;
@BenchmarkMode({
Mode.AverageTime
})
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 3, time = 5)
@Measurement(iterations = 3, time = 5)
@Threads(50)
@Fork(1)
@State(Scope.Benchmark)
public class RandomBenchmark {
Random random = new Random();
ThreadLocal<Random> threadLocalRandomHolder = ThreadLocal.withInitial(new Supplier<Random>(){
@Override
public Random get() {
return new Random();
}
});
@Benchmark
public int random() {
return random.nextInt();
}
@Benchmark
public int threadLocalRandom() {
return ThreadLocalRandom.current().nextInt();
}
@Benchmark
public int threadLocalRandomHolder() {
return threadLocalRandomHolder.get().nextInt();
}
}
- 通过mvn clean package,对代码进行打包
- 执行java -jar ./target/benchmarks.jar (打好的包会放在target目录下)
-
运行结果如下图:
JMH运行结果
其中Score表示平均的运行时间,Error表示误差的范围。
JMH注解的含义
- @Benchmark:用于标识需要进行基准测试的方法
- @BenchmarkMode :用于指定性能数据的格式。主要用的有吞吐量或者平均时间。
- @OutputTimeUnit:用于指定输出的时间单位。
- @Warmup:用于对预热迭代进行配置,包括iterations配置预热次数,time配置预热时间, timeUnit配置时间单位,以及batchSize执行次数。
- @Measurement:用于对测试迭代进行配置,各参数含义跟Warmup一样。
- @Threads:用于配置测试时的线程数。
- @Fork:允许开发人员指定所要 Fork 出的 Java 虚拟机的数目。
- @State:用于标识程序的状态,其中:Scope.Thread:默认的State,每个测试线程分配一个实例;Scope.Benchmark:所有测试线程共享一个实例,用于测试有状态实例在多线程共享下的性能;Scope.Group:每个线程组共享一个实例;
- @Setup和@TearDown:用于测试前对程序状态的初始化以及测试后对程序状态的恢复或者校验。
原理
JMH 的注解处理器自动生成真正的性能测试代码,以及相应的性能测试配置文件。我们可以在maven的target目录下的generated-sources查看JMH帮我们生成的一些类。
网友评论