Posted in

FastJson、Jackson、Gson、Hutool,JSON 解析哪家强?JMH 基准测试来排行_AI阅读总结 — 包阅AI

包阅导读总结

1. 关键词:JSON 解析、JMH 基准测试、FastJson、序列化、反序列化

2. 总结:本文针对市面上主流的 5 种 JSON 解析工具,使用 JMH 基准测试对小、中、大 JSON 的序列化和反序列化共 6 项指标进行测试,并给出测试排行榜和分析。

3. 主要内容:

– 引言

– 介绍对 JSON 解析工具进行测试的原因,包括其应用广泛及对系统性能的影响。

– 准备工作

– 介绍 JMH 基准测试及代码。

– 说明测试的 JSON 工具版本。

– 给出测试平台信息。

– 定义小、中、大 JSON 的测试数据。

– JSON 序列化测试

– 小 JSON 序列化测试

– 跑分结果及排名。

– 中 JSON 序列化测试

– 跑分结果及排名。

– 大 JSON 序列化测试

– 跑分结果及排名。

– JSON 反序列化测试

– 小 JSON 反序列化测试

– 跑分结果及排名。

– 中 JSON 反序列化测试

– 跑分结果及排名。

– 大 JSON 反序列化测试

– 跑分结果及排名。

思维导图:

文章地址:https://juejin.cn/post/7411797476673847346

文章来源:juejin.cn

作者:赵侠客

发布时间:2024/9/8 23:03

语言:中文

总字数:4284字

预计阅读时间:18分钟

评分:88分

标签:JSON解析,JMH基准测试,性能对比,Java开发,开源库


以下为原文内容

本内容来源于用户推荐转载,旨在分享知识与观点,如有侵权请联系删除 联系邮箱 media@ilingban.com

首发公众号:【赵侠客】

引言

在前面《释放你九成的带宽和内存:GZIP在解决Redis大Key方面的应用》一文中我使用GZIP算法对JSON格式数据进行了压缩,可以减小88%的空间,文中也提到了目前JSON格式在我们项目中应用的非常广泛几乎无处不在。压缩JSON格式数据可以大大降低我们的存储和带宽成本,我们知道数据格式的转换过程是需要消耗CPU计算资源的,JSON格式数据转换的快慢也会直接影响我们接口响应的快慢,甚至影响我们系统的吞吐量,所以本文针对市面上主流的5种JSON解析工具FastJson、FastJson2、JackSon、Gson、Hutool-JSON使用JAVA基准测试分别对小JSON、中JSON、大JSON的序列化和返序列化共6项指标进行测试,最后给出了测试排行榜,希望最后的排行榜能对您在做JSON工具选型时有一定的帮助。

二、准备工作

2.1 JMH基准测试

平时我们做代码性能测试可能就是在代码执行前通过System.currentTimeMillis()获取一下当前时间,代码执行后再获取一个当前时间,然后两个时间相减得出代码的运行时间,这种测试是非常不准确的,包括获取时间的精度、JIT编译优化导致性能测试结果不稳定、系统当前的负载,包括CPU、内存、磁盘I/O等会影响测试结果、Java虚拟机(JVM)需要一段时间来预热也会影响测试结果。所以为了测试的准确性,本文使用JMH(Java Microbenchmark Harness)进行测试,JMH是由OpenJDK/Oracle维护的Java基准测试工具,它旨在帮助开发人员编写准确的基准测试,以避免常见的基准测试陷阱,并提供可靠的性能测试结果。因为使用的JMH基准测试所以测试结果应该是有说服力的。

添加JMH Maven依赖:

<dependency>    <groupId>org.openjdk.jmh</groupId>    <artifactId>jmh-core</artifactId>    <version>1.36</version></dependency><dependency>    <groupId>org.openjdk.jmh</groupId>    <artifactId>jmh-generator-annprocess</artifactId>    <version>1.36</version></dependency>

JMH测试代码:

@State(Scope.Thread)public class HelloBenchmark {    @Benchmark    public void testMethod() throws InterruptedException {        Thread.sleep(10);    }    @Test    public void testBenchmark() throws Exception {        Options options = new OptionsBuilder()                .include(HelloBenchmark.class.getSimpleName())                .forks(1)                 .threads(1)                 .warmupIterations(1)                 .measurementIterations(1)                .mode(Mode.Throughput)                .build();        new Runner(options).run();    }}

JMH测试结果:

Benchmark   Mode   Score    UnitstestMethod  thrpt  64.579   ops/s

2.2 测试JSON工具的版本

同一款工具不同的版本性能差距往往比较明显,针对被测试的5种JSON解析工具选择了目前主流的版本,本文测试的结果也仅限于以下版本:

Tool 版本
FastJson2 2.0.52
FastJson 1.2.83
Jackson 2.17.2
Gson 2.11.0
Hutool 5.8.23

以下为各工具版本对应的Maven依赖:

<dependency>    <groupId>com.alibaba.fastjson2</groupId>    <artifactId>fastjson2</artifactId>    <version>2.0.52</version></dependency><dependency>    <groupId>com.alibaba</groupId>    <artifactId>fastjson</artifactId>    <version>1.2.83</version></dependency><dependency>    <groupId>com.fasterxml.jackson.core</groupId>    <artifactId>jackson-core</artifactId>    <version>2.17.2</version></dependency><dependency>    <groupId>com.fasterxml.jackson.core</groupId>    <artifactId>jackson-databind</artifactId>    <version>2.17.2</version></dependency><dependency>    <groupId>com.google.code.gson</groupId>    <artifactId>gson</artifactId>    <version>2.11.0</version></dependency><dependency>    <groupId>cn.hutool</groupId>    <artifactId>hutool-json</artifactId>    <version>5.8.23</version></dependency>

2.3 测试平台

测试代码跑出的得分是依赖于JDK版本和运行代码的机器,不同机器跑出的得分差异是很大的,以下是我的测试机器、JDK版本和IDE版本:

  • 硬件 : MacBook Pro 16GB 13英寸 M2 2022 macOS Ventura 13.5.1 (22G90)
  • JDK : Azul Zulu 17.0.8 – aarch64
  • IDE : IntelliJ IDEA 2024.2 (Ultimate Edition

2.4 测试代码

测试中我针对小JSON中JSON大JSON做序列化和反序列化跑分。其中小、中、大JSON我的定义为:

任何一个系统都会有用户信息,我想获取用户详情接口返回的用户信息JSON应该是最能代表我们日常项目开发中对小JSON的定义,所以我选择一条用户信息做为小JSON来做序列化和反序列化测试。以下为用户对象的定义:

@Datapublic class User {    private Long id;    private String name;    private String trueName;    private Integer age;    private String sex;    private Date createTime;}

在实际项目中我们除了有大量获取详情接口外,其次应该就是获取列表接口了,一般分页返回数据条数为10条或者20条,这里我选取20条用户信息做为我对中JSON的测试数据,我想这应该是非常具有代表性的中JSON数据。中JSON的数据定义:

private List<User> users;@Setuppublic void setup() {    users = new ArrayList<>();    IntStream.range(1, 20).forEach(x -> {        User user = new User();        user.setId(1L);        user.setName(RandomUtil.randomString("公众号:赵侠客",100));        user.setAge(29);        user.setSex("男");        user.setTrueName(RandomUtil.randomString("公众号:赵侠客",100));        user.setCreateTime(new Date());        users.add(user);    });}

每个项目中大JSON可能都不一样,我以博客系统为例,我觉得大JSON可能就是文章正文中的HTML富文本数据,所以测试数据中的大JSON我选择了公众号文章详情页中的HTML富文本数据。以下为大JSON对象定义:

@Datapublic class Article {    private Long id;    private String author;    private Long tenantId;    private String title;    private String subTitle;    private String htmlContent;    private Date publishTime;}@Setuppublic void setup() throws IOException {    article = new Article();    article.setId(10000L);    article.setTenantId(10000L);    article.setAuthor("公众号:赵侠客");    article.setPublishTime(new Date());    article.setTitle(RandomUtil.randomString("主标题", 100));    article.setSubTitle(RandomUtil.randomString("副标题", 50));    article.setHtmlContent(new String(Files.readAllBytes(Paths.get("article.html"))));}

大JSON部分数据内容

完成对小JSON,中JSON,大JSON数据的定义后,就可以使用JMH做基准测试了,以下为小JSON序列化测试代码:

@State(Scope.Thread)public class SmallJsonSerialize {    private User user;    private ObjectMapper mapper;    private Gson gson;    @Setup    public void setup() {        user = new User();        user.setId(1L);        user.setName("赵侠客");        user.setAge(29);        user.setSex("男");        user.setTrueName("公众号");        user.setCreateTime(new Date());        mapper = new ObjectMapper();        gson = new Gson();    }    @TearDown    public void tearDown() {        user = null;        mapper = null;        gson = null;    }    @Benchmark    public void testFastJson() {        String json = JSON.toJSONString(user);    }    @Benchmark    public void testFast2Json() {        String json = com.alibaba.fastjson2.JSON.toJSONString(user);    }    @Benchmark    public void testHutoolJson() {        String json = JSONUtil.toJsonStr(user);    }    @Benchmark    public void testJackson() throws JsonProcessingException {        String json = mapper.writeValueAsString(user);    }    @Benchmark    public void testGson() {        String json = gson.toJson(user);    }    @Test    public void testBenchmark() throws Exception {        Options options = new OptionsBuilder()                .include(SmallJsonSerialize.class.getSimpleName())                .forks(1)                .threads(1)                .warmupIterations(1)                .measurementIterations(1)                .mode(Mode.Throughput)                .build();        new Runner(options).run();    }}

三、JSON序列化测试

3.1 小JSON序列化测试

3.1.1 小JSON序列化跑分:

Benchmark    Score        UnitsFastJson2    13653527.046 ops/sFastJson     8502829.931  ops/sGson         1217934.274  ops/sHutoolJson   437293.524   ops/sJackson      5779830.068  ops/s

从结果的值来看小JSON序列化都是非常快的,我们的HTTP接口响应时间基本上都是在几十毫秒到几秒之间,对小JSON做一次序列化可以说对我们的接口性能没有任何影响,如果你的项目只有这些小JSON感觉可以闭眼选工具,项目中引用了哪个就用哪个或者哪个用的习惯就用哪个,把主要精力放在业务上没必要太纠结JSON工具的选型。不过今天我们是极客,要有追究极致的精神,我对5种结果做了得分的排名,Score为JMH的跑分,

百分制:最大Score的得100分,其它为 100*(Score/最大值)

3.1.2 小JSON序列化排名:

Tool Score 百分制
FastJson2 13653527 100
FastJson 8502829 62.3
Jackson 5779830 42.3
Gson 1217934 8.9
Hutool 437293 3.2

看到这个排名后我有两点想说的:

  • FastJson2,无敌是多么,多么寂寞
  • Hutool,@所有人,大家看看自己在项目中有没有使用Hutool-Json,有用到的来下我办公室

3.2 中JSON序列化测试

3.2.1 中JSON序列化跑分:

Benchmark   Score       UnitsFastJson2   236910.655  ops/sFastJson    173386.528  ops/sGson        50937.391   ops/sHutoolJson  10928.165   ops/sJackson     212457.203  ops/s

对于中JSON序列化来说分值就大幅度下降了,最差的Hutool 一秒只能序列化1万多次,也就是说做一次JSON转换需要0.1毫秒,做10次也就是1毫秒,如里接口中有大量中JSON序列化调用会对我们接口响应时间有一定影响。

3.2.2 中JSON序列化排名:

Tool Score 百分制
FastJson2 236910 100
Jackson 212457 89.7
FastJson 173386 73.2
Gson 50937 21.5
Hutool 10928 4.6

看到这个排名后我有二点想说的:

  • FastJson2,无敌是多么,多么空虚
  • Hutool,@所有人,大家看看自己在项目中有没有使用Hutool-Json,有用到的来下我办公室

3.3 大JSON序列化测试

3.3.1 大JSON序列化跑分:

Benchmark    Score     UnitsFastJson2   9650.211   ops/sFastJson    4791.032   ops/sGson        5835.649   ops/sHutoolJson  1035.357   ops/sJackson     13398.324  ops/s

大JSON的序列化得分已经降到最差的Hutool-Json执行一次需要1毫秒了,我这还是在M2上跑的,然后我又在PC电脑上跑了一下:

Benchmark   Score      UnitsFast2Json   5788.067   ops/sFastJson    2480.132   ops/sGson        2176.535   ops/sHutoolJson  455.914    ops/sJackson     5276.439   ops/s

上面是在 Intel(R) Core(TM) i7-4790K CPU @ 4.00GHz跑的结果,可以看出最差了执行一次JSON序列化需要2毫秒,所参大JSON解析的快慢非常影响我们的接口性能了。

3.3.2 大JSON序列化排名:

Tool Score 百分制
Jackson 13398 100
FastJson2 9650 72.0
Gson 5835 43.6
FastJson 4791 35.8
Hutool 1035 7.7

看到这个排名后我有二点想说的:

  • Jackson,做为SpringBoot默认json序列化工具是有原因的
  • Hutool,@所有人,大家看看自己在项目中有没有使用Hutool-Json,有用到的来下我办公室

四、JSON反序列化测试

4.1 小JSON反序列化测试

4.1.1 小JSON反序列化跑分:

Benchmark   Score        UnitsFastJson2  11654586.191  ops/sFastJson   5980216.867   ops/sGson       2415733.238   ops/sHutoolJson 855421.710    ops/sJackson    3194855.332   ops/s

4.1.2 小JSON反序化排名:

Tool SS SDS 变化 百分制
FastJson2 13653527 11654586 -14.6% 100
FastJson 8502829 5980216 -29.7% 51.3
Jackson 1217934 3194855 +162.3% 27.4
Gson 437293 2415733 +452.4% 20.7
Hutool 5779830 855421 -85.2% 7.3

其中:

  • SS( Small Serialize) ,小JSON序列化跑分,
  • SDS(Small Deserializer) ,小JSON反序列化跑分
  • 变化,相比自身小JSON序列化跑分增减百分比

看到这个排名后我有四点想说的:

  • FastJson2,无敌是多么,多么寂寞
  • Jackson&Gson,相比于序列化反序列化快多了
  • FastJson&FastJson2,你很强但是却输给了自己
  • Hutool,@所有人,大家看看自己在项目中有没有使用Hutool-Json,有用到的来下我办公室

4.2 中JSON反序列化测试

4.2.1 中JSON反序列化跑分:

Benchmark  Score         UnitsFastJson2   691572.756   ops/sFastJson    495493.338   ops/sGson        174852.543   ops/sHutoolJson  37997.839    ops/sJackson     216731.673   ops/s

4.2.2 中JSON反序列化排名:

Tool MS MDS 变化 百分制
FastJson2 236910 691572 +191.9% 100
FastJson 173386 495493 +185.8% 71.6
Jackson 212457 216731 -2.0% 31.3
Gson 50937 174852 +243.3% 25.3
Hutool 50937 37997 -25.4% 5.5

其中:

  • MS(Medium Serialize) ,中JSON序列化跑分,
  • MDS(Medium Deserializer) ,中JSON反序列化跑分
  • 变化,相比自身中JSON序列化跑分增减百分比

看到这个排名后我有三点想说的:

  • FastJson2,无敌是多么,多么空虚
  • FastJson2&FastJson,不但强还比自己序列化强
  • Hutool,@所有人,大家看看自己在项目中有没有使用Hutool-Json,有用到的来下我办公室

4.3 大JSON反序列化测试

4.3.1 大JSON反序列化跑分:

Benchmark   Score     UnitsFastJson2   8555.106  ops/sFastJson    9002.889  ops/sGson        6141.212  ops/sHutoolJson  1252.990  ops/sJackson     4614.815  ops/s

4.3.2 大JSON反序列化排名:

Tool BS BDS 变化 百分制
FastJson 4791 9002 +87.9 100
FastJson2 9650 8555 -11.3 95.0
Gson 5835 6141 +5.2 68.2
Jackson 13398 4614 -65.6 51.3
Hutool 1035 1252 +20.9 13.9

其中:

  • BS(Big Serialize) ,大JSON序列化跑分
  • BDS(Big Deserializer) ,大JSON反序列化跑分
  • 变化,相比自身大JSON序列化跑分增减百分比

看到这个排名后我有三点想说的:

  • FastJson2,青出于蓝而胜于蓝,可是你没想到人家还留了一手
  • FastJson,教会徒弟饿死师傅这个道理你是懂的
  • Hutool,@所有人,大家看看自己在项目中有没有使用Hutool-Json,有用到的来下我办公室

排行榜

Tool 排名 总分 百分制 SS MS BS SDS MDS BDS
FastJson2 状元 567 100 100 100 72.0 100 100 95.0
FastJson 榜眼 394.2 69.5 62.3 73.2 35.8 51.3 71.6 100
Jackson 探花 342 60.3 42.3 89.7 100 27.4 31.3 51.3
Gson 进士 188.2 33.2 8.9 21.5 43.6 20.7 25.3 68.2
Hutool 孙山 42.2 7.4 3.2 4.6 7.7 7.3 5.5 13.9

其中:

  • 排名,根据总得分降序
  • 总分,6项得分总和
  • 百分制,总得分最大为100分, 100*(最大总分-自己)/(最大总分)
  • SS,小JSON序列化得分
  • MS,中JSON序列化得分
  • BS,大JSON序列化得分
  • SDS,小JSON反序列化得分
  • MDS,中JSON反序列化得分
  • BDS,大JSON反序列化得分

JSON解析性能排行榜

看到这个排行榜后我有5点想说的:

  • FastJson2,无敌是多么,多么寂寞、无敌是多么,多么空虚
  • FastJson,长江后浪推前浪,前浪被拍在沙滩,你的漏洞那么多,该退休了
  • Jackson,SpringBoot看上的没毛病
  • Gson,你没存在感的原因要从别人找起,不是你不优秀,是优秀的人了太多了
  • Hutool, @公众号 @赵侠客 你们两个工作交接一下,明天不用来了

最后本测试纯个人自娱自乐,由于本人开发水平有限,如果怀疑测试结果,可以评论区交流或者可以下载源码自己跑分:

GitHub:github.com/whzhaochao/…