Java中JSON库性能对比[Fastjson,Gson,Jackson]

目前Java中最热门的JSON库无疑是JacksonGsonFastjson三者,可以在Maven官方仓库中看到它们的应用广泛程度:https://mvnrepository.com/tags/json

Fastjson虽然在世界范围内远远不如JacksonGson,但是在国内它的使用者还是相当多的。就我自己而言,在工作中虽然三者都有使用,但是Fastjson用的更加频繁许多。

用的久了之后,便好奇三者性能差距究竟如何?于是乎便有了这篇文章,废话不多说,直接切入正题。

版本

性能测试采用的版本分别是:

  • fastjson: 1.2.51
  • jackson: 2.9.8
  • gson: 2.8.5

JMH

如果你深度使用过Golang语言的话,应该见识过其语言内置的强大的benchmark功能,不需要第三方库便可以直观地精准测试某个模块或函数的执行速度、内存消耗等。

JMH所提供的功能也是如此,它是一款非常出色的性能测试工具,你可以使用它测试指定方法的执行平均耗时、吞吐量、内存消耗等等多种指标,不需要关心JVM的预热、GC等等可能影响到测试结果准确度的外界因素。具体JMH的使用方式不再赘述,感兴趣的可以直接查看源代码,或者搜索相关文档。

接下来测试JSON序列化主要侧重于“平均耗时”与“内存消耗”。

序列化测试

先给出数据,具体数据指标的含义后面再综合讨论。

第一轮测试一个非常简单的POJO序列化,其源代码参见这里,测试结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Benchmark                                        Mode  Cnt     Score     Error   Units
fastjson2TreeBenchmark avgt 9 0.747 ± 0.026 us/op
fastjson2TreeBenchmark:·gc.alloc.rate.norm avgt 9 848.017 ± 0.056 B/op
fastjsonJsonBenchmark avgt 9 0.608 ± 0.014 us/op
fastjsonJsonBenchmark:·gc.alloc.rate.norm avgt 9 896.019 ± 0.050 B/op
fastjsonJsonBenchmark2 avgt 9 1.221 ± 0.038 us/op
fastjsonJsonBenchmark2:·gc.alloc.rate.norm avgt 9 1552.026 ± 0.065 B/op

gson2TreeBenchmark avgt 9 1.173 ± 0.234 us/op
gson2TreeBenchmark:·gc.alloc.rate.norm avgt 9 1936.025 ± 0.063 B/op
gsonJsonBenchmark avgt 9 1.534 ± 0.393 us/op
gsonJsonBenchmark:·gc.alloc.rate.norm avgt 9 2360.307 ± 0.663 B/op
gsonJsonBenchmark2 avgt 9 1.724 ± 0.378 us/op
gsonJsonBenchmark2:·gc.alloc.rate.norm avgt 9 3072.019 ± 0.063 B/op

jackson2TreeBenchmark avgt 9 0.563 ± 0.036 us/op
jackson2TreeBenchmark:·gc.alloc.rate.norm avgt 9 1184.016 ± 0.042 B/op
jacksonJsonBenchmark avgt 9 0.533 ± 0.027 us/op
jacksonJsonBenchmark:·gc.alloc.rate.norm avgt 9 792.015 ± 0.039 B/op
jacksonJsonBenchmark2 avgt 9 0.918 ± 0.126 us/op
jacksonJsonBenchmark2:·gc.alloc.rate.norm avgt 9 1896.016 ± 0.058 B/op

第二轮测试一个相对复杂的多层POJO序列化,其源代码参见这里,测试结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Benchmark                                       Mode  Cnt     Score     Error   Units
fastjson2TreeBenchmark avgt 9 1.748 ± 0.056 us/op
fastjson2TreeBenchmark:·gc.alloc.rate.norm avgt 9 2216.011 ± 0.052 B/op
fastjsonJsonBenchmark avgt 9 1.300 ± 0.053 us/op
fastjsonJsonBenchmark:·gc.alloc.rate.norm avgt 9 1648.004 ± 0.053 B/op
fastjsonJsonBenchmark2 avgt 9 2.983 ± 0.066 us/op
fastjsonJsonBenchmark2:·gc.alloc.rate.norm avgt 9 3448.018 ± 0.082 B/op

gson2TreeBenchmark avgt 9 2.379 ± 0.136 us/op
gson2TreeBenchmark:·gc.alloc.rate.norm avgt 9 4208.025 ± 0.083 B/op
gsonJsonBenchmark avgt 9 3.261 ± 0.365 us/op
gsonJsonBenchmark:·gc.alloc.rate.norm avgt 9 4848.562 ± 40.343 B/op
gsonJsonBenchmark2 avgt 9 3.905 ± 0.344 us/op
gsonJsonBenchmark2:·gc.alloc.rate.norm avgt 9 6469.366 ± 107.471 B/op

jackson2TreeBenchmark avgt 9 1.237 ± 0.035 us/op
jackson2TreeBenchmark:·gc.alloc.rate.norm avgt 9 2760.019 ± 0.063 B/op
jacksonJsonBenchmark avgt 9 1.043 ± 0.015 us/op
jacksonJsonBenchmark:·gc.alloc.rate.norm avgt 9 1520.017 ± 0.058 B/op
jacksonJsonBenchmark2 avgt 9 2.436 ± 0.074 us/op
jacksonJsonBenchmark2:·gc.alloc.rate.norm avgt 9 6920.012 ± 100.840 B/op

测试结果说明:

  • *2Tree测试直接将Object转换为NodeTree的性能指标。
  • *JsonBenchmark测试常用的Object序列化为JSON的性能指标。
  • *JsonBenchmark2测试将Object转换为NodeTree然后再toString的性能指标。

指标说明:

  • 无后缀的Benchmark,表示默认的平均单次执行耗时,单位为微秒(us/op)。
  • gc.alloc.rate.norm,表示单次序列化过程中的内存消耗量,单位为字节(B/op)。
  • 其他还有一些性能指标,可以点击源代码链接进入查看。

我本以为各个序列号库的实现,应该都是先将Object转换为NodeTree,然后再格式化为字符串,但是从测试结果来看并非如此。

普通Object转换为JSON的话,Jackson的处理速度比Fastjson高约10%~20%,比Gson高约200%。内存消耗上Jackson也是相同比例地优于FastjsonGson

反序列化性能测试

测试反序列化一个长度大概2KB的json字符串,其源代码参见这里,测试结果如下:

1
2
3
4
5
6
7
Benchmark                              Mode  Cnt      Score      Error   Units
fastjson2Tree avgt 9 8.511 ± 0.227 us/op
fastjson2Tree:·gc.alloc.rate.norm avgt 9 15392.001 ± 0.001 B/op
gson2Tree avgt 9 9.203 ± 0.235 us/op
gson2Tree:·gc.alloc.rate.norm avgt 9 20768.001 ± 0.001 B/op
jackson2Tree avgt 9 7.966 ± 0.318 us/op
jackson2Tree:·gc.alloc.rate.norm avgt 9 16024.001 ± 0.001 B/op

注意:此项测试是将JSON字符串解析为JsonNode而非直接转换为POJO实例。

普通长度的Json字符串解析为JsonNode的处理速度上,三个库的耗时差距不大,相比而言Jackson仍然更加快一些。但是内存消耗上,Jackson略弱于Fastjson

后言

本文主要针对笔者日常工作中常用的普通数据类型进行性能测试,而没有对小、中、大数据的全覆盖测试,或许个别库对大JSON数据有更好的性能优化,感兴趣的同仁可以深入测试。

整体而言,Jackson无愧于大家对它的厚爱,处理速度与内存消耗整体都优于FastjsonGson

早年间Fastjson大肆宣传其“性能碾压”竞品,许多博文用“Fastjson非常快Jackson较快Gson一般”等吸引眼球的结论推荐等,导致国内大量从业者首选Fastjson。但时至今日,其仍然只能在中文圈传播,还是说明了一些问题的,但是侧面来讲,阿里的工程师们确实非常擅长推广。

Jackson作为JSON库的王者,除了性能顶尖之外,它的源码也是相当优秀的,起码比“无注释”的Fastjson好得多。设计上也提供了非常好的扩展性,也支持丰富的自定义功能。千言万语汇成一句话,良心推荐。

Gson的存在比较尴尬,我想不到使用它的理由,可能移动端有针对性的优化?