反序列化是 Android 开发中必备且十分高频的需求,因此一个高性能的反序列化结构就十分重要了,那么在常用的 Gson, Moshi, Jackson, Kotlin Serialization, FastJson 等结构中,到底谁比较快?

测验方法

  • 通过 Jetpack Microbenchmark 库进行基准测验,以避免 CPU 降频,JIT 优化对测验成果的影响
  • 测验用例输入包含 12kb, 78kb, 238kb 大小的三个 json 文件,以测验 json 大小对反序列化速度的影响
  • 测验成果分为屡次运转充分预热与一次运转无预热两种情况,以测验在冷启动情况下反序列化速度的差异

测验代码

测验代码可见:github.com/RicardoJian…

测验成果

屡次运转测验成果

small json medium json large json
Kotlin Serialization 165,936 ns 997,228 ns 2,933,098 ns
JSONReader 190,902 ns 1,164,605 ns 3,412,914 ns
FastJson 196,860 ns 1,417,077 ns 4,218,987 ns
JSONObject 258,789 ns 1,690,190 ns 4,788,937 ns
Moshi 303,056 ns 1,411,364 ns 3,955,789 ns
Gson 412,421 ns 1,356,564 ns 3,557,943 ns
Jackson 1,073,504 ns 1,798,989 ns 3,543,983 ns

常用 JSON 库性能对比: Gson VS Moshi VS Kotlin Serialization VS ...

从柱状图能够很明显的看出各个结构的速度比照

  • Kotlin Serialization 看起来是最适合 Kotlin 的反序列化结构,在各个结构中体现最好
  • JSONReader 与 JSONObject 在小数据上体现也不错,在大数据上 JSONReader 与其它结构相差不大,而 JSONObject 由于要将 InputStream 转化成 String,体现较差
  • FastJson 在小数据时的确比较快,但是在大数据时比较其它结构没有什么优势,一起在没有无参结构函数时,FastJson 会运用 Kotlin 反射来反序列化,此时速度反序列化速度将大幅下降
  • Moshi 与 Gson 在反序列化速度上差距不大,基本上是一个量级
  • Jackson 在小数据反序化速度比较其它结构明显较慢,在大数据情况下则相差不大

一次运转测验成果

small json medium json large json
Kotlin Serialization 4,114,323 ns 15,739,688 ns 17,428,906 ns
JSONReader 630,469 ns 2,052,501 ns 5,630,261 ns
FastJson 61,629,844 ns 6,756,823 ns 10,529,791 ns
JSONObject 580,469 ns 2,227,290 ns 6,311,667 ns
Moshi 4,460,886 ns 13,854,792 ns 18,951,198 ns
Gson 3,319,688 ns 5,568,906 ns 10,264,635 ns
Jackson 15,070,469 ns 13,625,521 ns 17,914,687 ns

常用 JSON 库性能对比: Gson VS Moshi VS Kotlin Serialization VS ...

能够看出,一次运转测验成果与屡次运转测验成果明显不同

  • JSONReader 与 JSONObject 比较其它结构优势明显,在冷启动场景运用这些体系原生 API 应该会有一定优势,这也是 MSON 结构提高反序列化速度的原理
  • FastJson 在初次运转时明显慢于其它结构,后续则恢复正常速度,与 Gson 速度差不多,快于 Moshi
  • 在冷启动场景,Moshi 与 Kotlin Serialization 速度差不多,比较 Gson 则略慢
  • Jackson 初次运转时较慢,后续与 Moshi 速度相似

与 Protobuf 比较

Protobuf 全称:Protocol Buffers,是 Google 推出的一种与平台无关、言语无关、可扩展的简便高效的序列化数据存储格式。

Protobuf 数据以二进制格式存储,比较 json 占用体积要小许多,比如我们将上面的 json 文件转化成 Protobuf 二进制文件之后,体积缩小了 50% 左右。

接下来我们来看下 Protobuf 反序列化的速度比较 json 到底怎么样。

屡次运转测验成果

small data medium data large data
Kotlin Serialization 171,134 ns 1,010,621 ns 2,945,403 ns
JSONReader 191,611 ns 1,165,174 ns 3,426,443 ns
Protobuf 108,520 ns 576,859 ns 1,674,978 ns

我们将 Protobuf 与之前体现比较优异的 Kotlin Serialization 与 JSONReader 进行比照,能够看出 Protobuf 的反序列化速度比较之前体现最优异的 Kotlin Serialization 也有 50% 左右的提高

一次运转测验成果

small data medium data large data
Kotlin Serialization 5,033,698 ns 15,217,709 ns 17,278,021 ns
JSONReader 519,167 ns 1,617,604 ns 5,623,749 ns
Protobuf 3,605,313 ns 6,869,480 ns 11,330,886 ns

能够看出在冷启动时,JSONReader 的体现仍是遥遥领先,而 Protobuf 的体现比 Kotlin Serialization 仍是要好一些。

当然运用 JSONReader 与 JSONObject 这些原生 API 需要写许多模板代码,能够运用相似 MSON 的方法,通过代码生成的方法减少开发本钱。

总结

  • Kotlin Serialization 是在纯 Kotlin 代码中反序列化 json 的最佳选择,速度最快
  • 假如能够牺牲可读性,运用 Protobuf 能够带来 50% 左右的体积与反序列化速度提高
  • 在冷启动场景中,运用 JSONReader 与 JSONObject 能够带来很大的性能提高。

当然性能测验的成果或许由于机型和数据的不同有所差异,欢迎运用测验代码进行测验,如有不同定见,欢迎在谈论区交流~

测验代码

测验代码可见:github.com/RicardoJian…