使用JMH进行基准测试(jackson序列化性能对比)

JMH简介

JMH(Java Microbenchmark Harness)是用于代码微基准测试的工具套件,主要是基于方法层面的基准测试,精度可以达到纳秒级。
该工具是由 Oracle 内部实现 JIT 的大牛们编写的,他们应该比任何人都了解 JIT 以及 JVM 对于基准测试的影响。
当你定位到热点方法,希望进一步优化方法性能的时候,就可以使用 JMH 对优化的结果进行量化的分析。
JMH 比较典型的应用场景如下:

  1. 想准确地知道某个方法需要执行多长时间,以及执行时间和输入之间的相关性。
  2. 对比接口不同实现在给定条件下的吞吐量。
  3. 查看多少百分比的请求在多长时间内完成。

快速入门

引入依赖,jdk 9之后默认引入;

<dependency>
	 <groupId>org.openjdk.jmh</groupId>
     <artifactId>jmh-core</artifactId>
     <version>1.37</version>
 </dependency>
 <dependency>
     <groupId>org.openjdk.jmh</groupId>
     <artifactId>jmh-generator-annprocess</artifactId>
     <version>1.37</version>
     <scope>provided</scope>
 </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 次测试
}

更多详细说明,参考知乎链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值