JMH是有OpenJDK开发的基准测试(Benchmark)工具。JMH可以为写基准测试和运行测试提供很好的支持。JMH在Concurrent Benchmarks也提供很好的支持,可以说是多功能测试工具。JMH在2013被公布出来,现在最新版本到1.9。
JMH基本用法:
JMH环境构建
1 使用maven工程,直接在项目中引入相应的jar包
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>${jmh.version}</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>${jmh.version}</version>
<scope>provided</scope>
</dependency>
2 或者直接用JMH的archetype创建:
mvn archetype:generate \
-DinteractiveMode=false \
-DarchetypeGroupId=org.openjdk.jmh \
-DarchetypeArtifactId=jmh-java-benchmark-archetype \
-DgroupId=com.yao \
-DartifactId=jmh-demo \
-Dversion=1.0
环境搭建好之后然后就可以写相应的测试用例了
Demo如下
public class JMHSample_01_HelloWorld {
@Benchmark
public void wellHelloThere() {
// this method was intentionally left blank.
}
/*
* a) Via command-line:
* $ mvn clean install
* $ java -jar target/benchmarks.jar JMHSample_01
*
* JMH generates self-contained JARs, bundling JMH together with it.
* The runtime options for the JMH are available with "-h":
* $ java -jar target/benchmarks.jar -h
*
* b) Via the Java API:
* (see the JMH homepage for possible caveats when running from IDE:
* http://openjdk.java.net/projects/code-tools/jmh/)
*/
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(JMHSample_01_HelloWorld.class.getSimpleName())
.forks(1)
.build();
new Runner(opt).run();
}
运行上面的Demo有两种方法:一个是直接打包,然后会在target中生成benchmarks.jar,里面带有main方法,就直接可以运行:java -jar target/benchmarks.jar。运行后的结果如下格式:(运行的结果也写入指定的文件)
Result "wellHelloThere":
3142305096.924 ±(99.9%) 17949665.603 ops/s [Average]
(min, avg, max) = (2907217981.526, 3142305096.924, 3226536099.659), stdev = 76000008.112
CI (99.9%): [3124355431.320, 3160254762.527] (assumes normal distribution)
# Run complete. Total time: 00:06:42
Benchmark Mode Cnt Score Error Units
MyBenchmark.testMethod thrpt 200 3142305096.924 ± 17949665.603 ops/s
同时也支持在IDE中直接运行。
往往在写用例的时候,可以不写main方法,直接在方法上写个Junit的Test注解 ,功能和main相同。
比如netty5中为所有的benchmarks写了一个基类如下:
@Warmup(iterations = AbstractMicrobenchmark.DEFAULT_WARMUP_ITERATIONS)
@Measurement(iterations = AbstractMicrobenchmark.DEFAULT_MEASURE_ITERATIONS)
@Fork(AbstractMicrobenchmark.DEFAULT_FORKS)
@State(Scope.Thread)
public class AbstractMicrobenchmark {
protected static final int DEFAULT_WARMUP_ITERATIONS = 10;
protected static final int DEFAULT_MEASURE_ITERATIONS = 10;
protected static final int DEFAULT_FORKS = 2;
public static final class HarnessExecutor extends ThreadPoolExecutor {
public HarnessExecutor(int maxThreads, String prefix) {
super(0, maxThreads, 1L, TimeUnit.DAYS, new SynchronousQueue<Runnable>(),
new DefaultThreadFactory(prefix));
System.out.println("Using harness executor");
}
}
protected static final String[] JVM_ARGS = {
"-server", "-dsa", "-da", "-ea:io.netty...", "-Xms768m", "-Xmx768m",
"-XX:MaxDirectMemorySize=768m", "-XX:+AggressiveOpts", "-XX:+UseBiasedLocking",
"-XX:+UseFastAccessorMethods", "-XX:+UseStringCache", "-XX:+OptimizeStringConcat",
"-XX:+HeapDumpOnOutOfMemoryError", "-Dio.netty.noResourceLeakDetection",
"-Dharness.executor=CUSTOM",
"-Dharness.executor.class=io.netty.microbench.util.AbstractMicrobenchmark$HarnessExecutor"
};
static {
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED);
}
@Test
public void run() throws Exception {
String className = getClass().getSimpleName();
ChainedOptionsBuilder runnerOptions = new OptionsBuilder()
.include(".*" + className + ".*")
.jvmArgs(JVM_ARGS);
if (getWarmupIterations() > 0) {
runnerOptions.warmupIterations(getWarmupIterations());
}
if (getMeasureIterations() > 0) {
runnerOptions.measurementIterations(getMeasureIterations());
}
if (getForks() > 0) {
runnerOptions.forks(getForks());
}
if (getReportDir() != null) {
String filePath = getReportDir() + className + ".json";
File file = new File(filePath);
if (file.exists()) {
file.delete();
} else {
file.getParentFile().mkdirs();
file.createNewFile();
}
runnerOptions.resultFormat(ResultFormatType.JSON);
runnerOptions.result(filePath);
}
new Runner(runnerOptions.build()).run();
}
protected int getWarmupIterations() {
return SystemPropertyUtil.getInt("warmupIterations", -1);
}
protected int getMeasureIterations() {
return SystemPropertyUtil.getInt("measureIterations", -1);
}
protected int getForks() {
return SystemPropertyUtil.getInt("forks", -1);
}
protected String getReportDir() {
return SystemPropertyUtil.get("perfReportDir");
}
}
我这里仅仅是入门性的介绍,具体的参数和用法本人也不是很熟悉。
具体介绍和用法参照:http://openjdk.java.net/projects/code-tools/jmh/
本人通过官网摘抄的例子,传到github上了:https://github.com/WangErXiao/jmh-demo
END-----------------------------------------------------------------------------------------
转发标注来源:http://my.oschina.net/robinyao/blog/408285
来源:oschina
链接:https://my.oschina.net/u/223302/blog/408285