JMH(Java Microbenchmark Harness)是用于代码微基准测试的工具套件,主要是基于方法层面的基准测试,精度可以达到纳秒级。
该工具是由 Oracle 内部实现 JIT 的大牛们编写的,他们应该比任何人都了解 JIT 以及 JVM 对于基准测试的影响。
当你定位到热点方法,希望进一步优化方法性能的时候,就可以使用 JMH 对优化的结果进行量化的分析。
JMH 比较典型的应用场景如下:
引入依赖,jdk 9之后默认引入;
<dependency>
<groupId>org.openjdk.jmhgroupId>
<artifactId>jmh-coreartifactId>
<version>1.37version>
dependency>
<dependency>
<groupId>org.openjdk.jmhgroupId>
<artifactId>jmh-generator-annprocessartifactId>
<version>1.37version>
<scope>providedscope>
dependency>
import com.fasterxml.jackson.databind.ObjectMapper;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.results.format.ResultFormatType;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @author JGMa
*/
@BenchmarkMode({Mode.Throughput})
@OutputTimeUnit(TimeUnit.SECONDS)
@State(Scope.Thread)
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(1)
@Threads(10)
public class ObjectMapperTest {
String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
// 定义内部状态类,作为基准测试的状态
@State(Scope.Benchmark)
public static class BenchmarkState {
ObjectMapper GLOBAL_MAP = new ObjectMapper();
// 每个线程独立的 ObjectMapper 实例
ThreadLocal<ObjectMapper> GLOBAL_MAP_THREAD = new ThreadLocal<>();
}
// 基准测试方法 - 使用全局的 ObjectMapper 实例
@Benchmark
public Map globalTest(BenchmarkState state) throws Exception {
// 使用全局 ObjectMapper 实例解析 JSON
Map map = state.GLOBAL_MAP.readValue(json, Map.class);
return map;
}
// 基准测试方法 - 使用线程本地的 ObjectMapper 实例
@Benchmark
public Map globalTestThreadLocal(BenchmarkState state) throws Exception {
if (null == state.GLOBAL_MAP_THREAD.get()) {
// 若线程本地的 ObjectMapper 实例未初始化,则创建一个新的实例
state.GLOBAL_MAP_THREAD.set(new ObjectMapper());
}
// 使用线程本地的 ObjectMapper 实例解析 JSON
Map map = state.GLOBAL_MAP_THREAD.get().readValue(json, Map.class);
return map;
}
// 基准测试方法 - 使用局部的 ObjectMapper 实例
@Benchmark
public Map localTest() throws Exception {
// 创建局部的 ObjectMapper 实例
ObjectMapper objectMapper = new ObjectMapper();
// 使用局部的 ObjectMapper 实例解析 JSON
Map map = objectMapper.readValue(json, Map.class);
return map;
}
public static void main(String[] args) throws Exception {
Options opts = new OptionsBuilder()
.include(ObjectMapperTest.class.getSimpleName())
.resultFormat(ResultFormatType.CSV)
.build();
// 运行基准测试
new Runner(opts).run();
}
// 基准测试方法名称 模式 执行次数 性能指标(次/秒) 误差(次) 单位(秒)
// Benchmark Mode Cnt Score Error Units
// ObjectMapperTest.globalTest thrpt 5 10787361.157 ± 943873.939 ops/s
// ObjectMapperTest.globalTestThreadLocal thrpt 5 11074100.930 ± 228239.867 ops/s
// ObjectMapperTest.localTest thrpt 5 924570.127 ± 85265.705 ops/s
// Mode(模式):表示基准测试的类型或模式。在这里,“thrpt” 是一种基于吞吐量(throughput)的模式。这种模式下,测试会计算单位时间内执行的操作次数。
// Cnt(执行次数):表示每个测试方法的执行次数。在这里,每个方法执行了 5 次测试
}
更多详细说明,参考知乎链接