Moshi Vs Gson Vs Kotlin Serialisation性能PK

Moshi Vs Gson Vs Kotlin Serialisation

定义

  • Gson

Gson 是一个Java序列化/反序列化库,用于将Java对象转换为JSON格式,以及将JSON格式转换回Java对象。

  • Moshi

Moshi 是一个现代化的JSON库,适用于Android和Java。它使得将JSON解析为Java对象以及将Java对象转换回JSON变得简单。

  • Kotlin序列化

Kotlin序列化是一种以Kotlin为主导的、在编译时类型安全、无反射且完全跨平台准备的序列化机制,用于将Kotlin对象转换为JSON或Protobuf等数据格式,反之亦然。该库不使用无反射,而是采用显式注解 @Serializable。应用该注解后,编译器插件会在伴生对象上添加一个特殊的函数 serializer(),返回类型为 KSerializer 的序列化器。KSerializer 对象实现了所需的接口,用于序列化和反序列化数据类。

性能比较

为了定义比较,创建了一个基准测试规则,可以总结如下代码片段:

class SerializableBenchMark {
    lateinit var json: Json
    lateinit var moshi: Moshi
    lateinit var gson: Gson
    lateinit var response: String
    private val context = InstrumentationRegistry.getInstrumentation().targetContext

    @Before
    fun setup() {
        json = Json {
            ignoreUnknownKeys = true
            isLenient = true
            encodeDefaults = false
            coerceInputValues = true
        }
        moshi = Moshi.Builder()
            .add(KotlinJsonAdapterFactory())
            .build()

        gson = GsonBuilder()
             .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
            .setLenient().create()

        response = context.assets.open("sample_response.json").use {
            it.bufferedReader().readText()
        }
    }
    @get:Rule
    val benchmarkRule = BenchmarkRule()

    @Test
    fun exampleKotlinSerialisation() = benchmarkRule.measureRepeated {
        json.decodeFromString(Response.serializer(), response)
    }

    @Test
    fun exampleMoshi() = benchmarkRule.measureRepeated {
        val jsonAdapter = moshi.adapter(Response::class.java)
        jsonAdapter.fromJson(response)
    }

    @Test
    fun exampleGson() = benchmarkRule.measureRepeated {
          gson.fromJson(response, Response.javaClass)
    }
}
  • 这里的 sample_response.json是从此链接构建的。

https://www.covidvisualizer.com/api

结果

测试用例 1 — 基准测试

我已记录了每个测试用例对应的 benchmark-data.json 文件,以便进行比较。

设备详情

"build": {
            "brand": "vivo",
            "device": "2130",
            "fingerprint": "vivo/2130i/2130:12/SP1A.210812.003/compiler05210733:user/release-keys",
            "model": "V2130",
            "version": {
                "sdk": 31
            }
        },
        "cpuCoreCount": 8,
        "cpuLocked": true,
        "cpuMaxFreqHz": 2500000000,
        "memTotalBytes": 12146495488,
        "sustainedPerformanceModeEnabled": false
    }

Kotlin -Serialisation

"benchmarks": [
        {
            "name": "PROFILED_exampleKotlinSerialisation",
            "params": {},
            "className": "com.example.benchmark.SerializableBenchMark",
            "totalRunTimeNs": 12119030155,
            "metrics": {
                "timeNs": {
                    "minimum": 3.802098385E9,
                    "maximum": 3.802098385E9,
                    "median": 3.802098385E9,
                    "runs": [
                        3.802098385E9
                    ]
                },
                "allocationCount": {
                    "minimum": 19390.0,
                    "maximum": 19390.0,
                    "median": 19390.0,
                    "runs": [
                        19390.0,
                        19390.0,
                        19390.0,
                        19390.0,
                        19390.0
                    ]
                }
            },
            "sampledMetrics": {},
            "warmupIterations": 2310,
            "repeatIterations": 1,
            "thermalThrottleSleepSeconds": 0
        }
    ]

Moshi

"benchmarks": [
        {
            "name": "PROFILED_exampleMoshi",
            "params": {},
            "className": "com.example.benchmark.SerializableBenchMark",
            "totalRunTimeNs": 11961625309,
            "metrics": {
                "timeNs": {
                    "minimum": 3.531992307E9,
                    "maximum": 3.531992307E9,
                    "median": 3.531992307E9,
                    "runs": [
                        3.531992307E9
                    ]
                },
                "allocationCount": {
                    "minimum": 14509.0,
                    "maximum": 16854.0,
                    "median": 14509.0,
                    "runs": [
                        16854.0,
                        14509.0,
                        14509.0,
                        14509.0,
                        14509.0
                    ]
                }
            },
            "sampledMetrics": {},
            "warmupIterations": 1202,
            "repeatIterations": 1,
            "thermalThrottleSleepSeconds": 0
        }
    ]

Gson

"benchmarks": [
        {
            "name": "PROFILED_exampleGson",
            "params": {},
            "className": "com.example.benchmark.SerializableBenchMark",
            "totalRunTimeNs": 1331248385,
            "metrics": {
                "timeNs": {
                    "minimum": 1.76971077E8,
                    "maximum": 1.76971077E8,
                    "median": 1.76971077E8,
                    "runs": [
                        1.76971077E8
                    ]
                },
                "allocationCount": {
                    "minimum": 20.0,
                    "maximum": 20.0,
                    "median": 20.0,
                    "runs": [
                        20.0,
                        20.0,
                        20.0,
                        20.0,
                        20.0
                    ]
                }
            },
            "sampledMetrics": {},
            "warmupIterations": 1062,
            "repeatIterations": 1,
            "thermalThrottleSleepSeconds": 0
        }
    ]

从上面的结果可以看出,Kotlin-serialisation 花费了 12.11 秒,Moshi 花费了 11.96 秒,而 Gson 花费了 13.31 秒。

测试用例 2 — 字段不存在

在这里,我从 US 节点中移除了 name 节点,如下截图所示。

Kotlin-Serialisation测试截图如下

Moshi测试截图如下

在这种情况下,Gson 忽略了该字段并完全执行了。

对于所有这些,我们可以看到 Moshi 的错误相对于其他两者来说更具体。

测试用例 3 - 使用基准报告

单次迭代结果

5次迭代结果

结论

总体而言,在序列化/反序列化方面,Moshi 显示出了良好的结果,但 Kotlin 序列化具有 Protobuf 支持,可以帮助降低延迟和有效载荷大小,因此根据用途,人们可以谨慎选择所需的库。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/49011.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

国内好用的企业级在线文档有哪些?

在当今数字化时代,企业级在线文档已经成为了现代办公环境中不可或缺的一部分。它不仅能够提高工作效率,还能够实现多人协同编辑,满足团队协作的需求。那么,在国内市场上,哪些企业级在线文档产品备受企业青睐呢&#xf…

25.1 Knife4j-Swagger的增强插件

1.Knife4j概述 Knife4j是一款基于Swagger UI的增强插件,它可以为Spring Boot项目生成美观且易于使用的API文档界面。它是Swagger UI的增强版,提供了更多的功能和定制选项,使API文档更加易读和易于理解。 2.Knife4j使用 Knife4j 集Swagger2…

嵌入式系统中的GPIO控制:从理论到实践与高级应用

本文将探讨嵌入式系统中的GPIO(通用输入输出)控制,着重介绍GPIO的原理和基本用法。我们将使用一个实际的示例项目来演示如何通过编程配置和控制GPIO引脚。将基于ARM Cortex-M微控制器,并使用C语言进行编写。 GPIO是嵌入式系统中最常见且功能最强大的接口之一。它允许硬件工…

LLM-Blender:大语言模型也可以进行集成学习

最近在看arxiv的时候发现了一个有意思的框架:LLM-Blender,它可以使用Ensemble 的方法来对大语言模型进行集成。 官方介绍如下:LLM-Blender是一个集成框架,可以通过利用多个开源大型语言模型(llm)的不同优势来获得始终如一的卓越性…

golang利用go mod巧妙替换使用本地项目的包

问题 拉了两个项目下来,其中一个项目依赖另一个项目,因为改动了被依赖的项目,想重新导入测试一下。 解决办法 go.mod文件的require中想要被代替的包名在replace中进行一个替换,注意:用来替换的需要用绝对路径&#xf…

机器视觉初步14:相机标定原理及应用

相机标定是指通过已知的相机参数,解算相机内部参数矩阵和外部参数矩阵。 文章目录 1.为什么要标定?2.工业场景中常见的标定方法2.1. 使用棋盘格标定板(Checkerboard Markers)2.2 使用相机自标定2.3. 使用三维物体标定2.4.九孔标…

【人工智能】神经网络、前向传播、反向传播、梯度下降、局部最小值、多层前馈网络、缓解过拟合的策略

神经网络、前向传播、反向传播 文章目录 神经网络、前向传播、反向传播前向传播反向传播梯度下降局部最小值多层前馈网络表示能力多层前馈网络局限缓解过拟合的策略前向传播是指将输入数据从输入层开始经过一系列的权重矩阵和激活函数的计算后,最终得到输出结果的过程。在前向…

【分布式】分布式唯一 ID 的 几种生成方案以及优缺点snowflake优化方案

在互联网的业务系统中,涉及到各种各样的ID,如在支付系统中就会有支付ID、退款ID等。那一般生成ID都有哪些解决方案呢?特别是在复杂的分布式系统业务场景中,我们应该采用哪种适合自己的解决方案是十分重要的。下面我们一一来列举一…

@monaco-editor/react组件CDN加载失败解决办法

monaco-editor/react引入这个cdn资源会load失败 网上很多例子都是这样写的,我这样写monaco会报错 import * as monaco from monaco-editor; import { loader } from monaco-editor/react;loader.config({ monaco });改成这样 import * as monaco from monaco-edi…

基于Centos 7虚拟机的磁盘操作(添加磁盘、分区、格式分区、挂载)

目录 一、添加硬盘 二、查看新磁盘 三、磁盘分区 3.1新建分区 3.2 格式分区 3.3 挂载分区 3.4 永久挂载新分区 3.5 取消挂载分区 一、添加硬盘 1.在虚拟机处选择编辑虚拟机设置,然后选择添加 2.选择硬盘,然后选择下一步 3.默认即可,下一步…

TCP连接管理与UDP协议

“三次握手”与“四次挥手” TCP建立连接的过程叫做握手 采用三报文握手:在客户和服务器之间交换三个TCP报文段,以防止已失效的连接请求报文段突然又传送到了,因而产生TCP连接建立错误。 第一次握手 连续释放——“四次挥手” TCP连续释放…

Zabbix监控之分布式部署

文章目录 Zabbix监控之分布式部署zabbix proxy概述部署zabbix-proxy节点规划基础环境准备安装proxy以及数据库配置数据库添加服务端host解析修改zabbix-proxy配置文件启动代理服务器 zabbix页面(1)在zabbix页面添加代理(2)zabbix-agent连接proxy Zabbix监控之分布式部署 zabbi…

使用Nacos将单体服务注册成微服务的步骤以及相关问题解决

目录 1.改造单体服务的配置文件。 2.添加Nacosw相关的pom依赖 3.在nacos的配置列表中创建配置列表 4.相关问题的解决 1.改造单体服务的配置文件。 🔖创建一个bootstrap.yml的配置文件该文件通常放置在src/main/resources目录中,并且优先于applicati…

ping命令

上图为IA ping B的过程,在此过程中: 包传送在x位置时,DestMacB左,SourceMacMac_A,Dest ipIp_B,Src_ipIp_A包传送在y位置时,DestMacB右,SourceMacB左 , Dest ipIp_B,Src_ipIp_A MAC…

多线程(Java系列6)

目录 前言: 1.什么是线程池 2.标准库中的线程池 3.实现线程池 结束语: 前言: 在上一节中小编带着大家了解了一下Java标准库中的定时器的使用方式并给大家实现了一下,那么这节中小编将分享一下多线程中的线程池。给大家讲解一…

三言两语说透process.stdout.write和console.log的区别

Node.js中的process.stdout.write和console.log都是用于向标准输出流(stdout)打印输出的方法,但二者在使用场景和实现方式上有些区别。本文将详细介绍process.stdout.write和console.log的区别。 process.stdout.write介绍 process.stdout.write是Node.js中的一个…

vue解决跨域访问问题(个人学习笔记六)

目录 友情提醒第一章、跨越问题解决1.1)什么是跨域问题?1.2)第一种解决方式:后端设置允许跨域访问1.3)第二种解决方式:前端配置代理 第二章、配置代理服务器2.1)配置简单代理服务器2.2&#xff…

Langchain 集成 Milvus

Langchain 集成 Milvus 1. 安装 Docker2. 部署 Milvus3.4. Langchain 集成 Milvus 1. 安装 Docker refer: https://docs.docker.com/engine/install/centos/ Milvus 会以容器方式启动,所以先安装 Docker。(本示例使用的是 Alma Linux 9.2) 卸载旧版本&#xff0c…

WEB APIs day4 (2)

三、M端事件 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width, …

深入学习 redis - Stream、Geospatial、HyperLogLog、Bitmap、Bitfields 类型扩展

目录 前言 Stream geospatial HyperLogLog Bitmaps Bitfields 前言 redis 中最关键的五个数据类型 String、List、Hash、Set、Zset 应用最广泛&#xff0c;同时 redis 也推出了额外的 5 个数据类型&#xff0c;他们分别是针对特殊场景才进行的应用的. Ps&#xff1a;这几种…