反序列化是 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 |
从柱状图能够很明显的看出各个结构的速度比照
- 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 |
能够看出,一次运转测验成果与屡次运转测验成果明显不同
- 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…