Go语言常见序列化协议全面对比

先说结论

从易用性、性能、内存占用、编码后大小等几个方面综合考虑 ProtoBuf 胜出。
Gob 从性能和 I/O 带宽占用上都和 ProtoBuf 差不多,唯一劣势是编解码时内存占用较多。考虑到不用再写 IDL 带来的易用性,如果整个系统内不存在使用除 Go 以外其他语言的服务,Gob 是更合适的选择。

jsonmsgpgobpbflatbuffers
易用性一般极差
性能
编解码内存占用一般
编码后大小
成熟度一般较好一般

测试场景

限制单核单线程场景,使用本地机器进行测试。
使用对象为 10 个字段对象,包括 string、int32、slice、map 等多种类型,且存在嵌套关系。

type Layer10 struct {IntField    int32StringField stringSliceField  []int32MapField    map[string]int32Field5      int32Field6      stringField7      []int32Field8      map[string]int32Field9      int32Field10     stringLayer10 *Layer10
}

主要验证 json、gob、msgp、pb、flatbuffers 这 5 种序列化方案。

场景1:层数逐渐增长

性能

这里不对CPU利用率做分析,原因是编解码属于纯计算密集型场景,每一种序列化方式都能跑满CPU。我们应该关注同等CPU性能下,序列化的效率。下面分别测试编解码混合、仅编码和仅解码的效率。
编解码混合
设定层级数从1层到100层递增,使用5种序列化方式进行编码+解码。
image.png
可以看出,在对象简单时(嵌套层级不超过5层),gob的性能不是很好,甚至比json更差;但在对象复杂度很高时,gob的性能优势就体现出来。
pb的性能略好于gob,二者的增长斜率基本一致。在应对复杂对象场景时,GOB性能要比JSON好一倍以上。
性能排名(>表示优于):FLAT > PB > GOB > MSGP > JSON

仅编码
image.png
JSON 的编码效率并不低,甚至能和 GOB 和 PB 保持在同一水平线上。

仅解码
image.png
解码效率拉开差距,JSON 解码性能很差,GOB 和 PB 较好,GOB 略低于 PB。

内存使用率

image.png
在序列化过程中,gob 需要消耗较多内存。而 pb 一直保持较低内存消耗
内存使用排序(>表示优于):PB > JSON > FLAT > MSGP >GOB

编码后大小

image.png
编码后,pb 和 gob 的长度都较小,基本不分伯仲。其他三种表现一般。
编码后大小排序(>表示优于):GOB > PB > FLAT > MSGP > JSON

以下是不同数量级时的性能表现:

# 层级为1时
Layer-1-Size-1-JSON         	    1000	      3887 ns/op	    1384 B/op	      34 allocs/op
Layer-1-Size-1-GOB          	    1000	     23707 ns/op	   13270 B/op	     333 allocs/op
Layer-1-Size-1-PB           	    1000	      1594 ns/op	    1000 B/op	      30 allocs/op
Layer-1-Size-1-MSGP         	    1000	      4139 ns/op	    2040 B/op	      59 allocs/op
Layer-1-Size-1-FLAT         	    1000	     6.708 ns/op	       1 B/op	       0 allocs/op# 层级为10时
Layer-10-Size-1-JSON        	    1000	     39244 ns/op	   11592 B/op	     256 allocs/op
Layer-10-Size-1-GOB         	    1000	     40830 ns/op	   27202 B/op	     623 allocs/op
Layer-10-Size-1-PB          	    1000	     17232 ns/op	    9280 B/op	     264 allocs/op
Layer-10-Size-1-MSGP        	    1000	     32549 ns/op	   15208 B/op	     431 allocs/op
Layer-10-Size-1-FLAT        	    1000	     20.79 ns/op	      13 B/op	       0 allocs/op# 层级为100时
Layer-100-Size-1-JSON       	    1000	    351715 ns/op	  111428 B/op	    2422 allocs/op
Layer-100-Size-1-GOB        	    1000	    183746 ns/op	  172531 B/op	    3509 allocs/op
Layer-100-Size-1-PB         	    1000	    162784 ns/op	   92208 B/op	    2604 allocs/op
Layer-100-Size-1-MSGP       	    1000	    315320 ns/op	  172416 B/op	    4125 allocs/op
Layer-100-Size-1-FLAT       	    1000	     88.75 ns/op	     120 B/op	       1 allocs/op

场景2:切片长度逐渐增长

设定一个[]Layer10,Layer10 只有一层,不做嵌套。切片中对象的数量逐渐增长

性能

image.png
与层级增长的情况一致,在对象简单时(列表长度不超过 15 个时),gob 的性能不是很好,甚至比 json 更差;但在对象复杂度很高时,gob 的性能优势才能体现出来。
性能排名:FLAT > PB > GOB > MSGP > JSON

内存使用率

image.png
结论同场景 1 一致

编码后大小

image.png
结论同场景 1 一致
不同数量级时的性能表现:

# 层级为1时
Layer-1-Size-1-JSON         	    1000	      3903 ns/op	    1384 B/op	      34 allocs/op
Layer-1-Size-1-GOB          	    1000	     23681 ns/op	   13267 B/op	     333 allocs/op
Layer-1-Size-1-PB           	    1000	      1614 ns/op	    1000 B/op	      30 allocs/op
Layer-1-Size-1-MSGP         	    1000	      4010 ns/op	    2040 B/op	      59 allocs/op
Layer-1-Size-1-FLAT         	    1000	     7.458 ns/op	       1 B/op	       0 allocs/op# 层级为10时
Layer-1-Size-10-JSON        	    1000	     37965 ns/op	   11592 B/op	     256 allocs/op
Layer-1-Size-10-GOB         	    1000	     40962 ns/op	   27205 B/op	     623 allocs/op
Layer-1-Size-10-PB          	    1000	     16340 ns/op	    9280 B/op	     264 allocs/op
Layer-1-Size-10-MSGP        	    1000	     31643 ns/op	   15208 B/op	     431 allocs/op
Layer-1-Size-10-FLAT        	    1000	     14.50 ns/op	      13 B/op	       0 allocs/op# 层级为100时
Layer-1-Size-100-JSON       	    1000	    388890 ns/op	  111420 B/op	    2422 allocs/op
Layer-1-Size-100-GOB        	    1000	    190858 ns/op	  172533 B/op	    3509 allocs/op
Layer-1-Size-100-PB         	    1000	    166676 ns/op	   92208 B/op	    2604 allocs/op
Layer-1-Size-100-MSGP       	    1000	    309114 ns/op	  172416 B/op	    4125 allocs/op
Layer-1-Size-100-FLAT       	    1000	     85.62 ns/op	     120 B/op	       1 allocs/op

分析

不管是嵌套层级数增加还是切片长度增加,整体趋势改变不大。各序列化方案的差异会随着对象复杂度的增加而拉大。
单从性能角度考虑,flatbuffers 的性能很好,原因是 flatbuffers 是直接向 ByteBuffer 里塞字节流的,就省掉了反射的步骤。但这样就牺牲了易用性。编写代码时,连set字段值的顺序都有非常严格的要求。这对研发的要求太高了,可能会导致很多问题。像这种极端难用的,除非有非常迫切的性能需要,否则肯定是不建议使用的。
综合考虑各方面因素,ProtoBuf 脱颖而出,但唯一不好的就是要写 IDL。是否可以通过二次开发或者包装工具的方式来抹平 IDL 带来的缺点。

Gob 从性能和 I/O 带宽占用上都和 ProtoBuf 差不多,唯一劣势是编解码时内存占用较多。考虑到不用再写IDL带来的易用性,在「只使用 Go 语言」的背景下,Gob 是更合适的选择。

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

使用 Snorkel 和 MinIO 的以数据为中心的 AI

如今,业界都在谈论大型语言模型及其编码器、解码器、多头注意力层和数十亿(即将数万亿)的参数,人们很容易相信好的人工智能只是模型设计的结果。不幸的是,事实并非如此。好的人工智能需要的不仅仅是一个精心设计的模型…

医疗器械ce认证办理流程介绍

CE认证是的产品安全认证,所有进入市场的医疗器械都必须进行医疗器械CE认证,医疗器械CE认证为了解决成员国之间的贸易壁垒,组织逐步将自己建成一个统一的大市场,以确保人员、服务、资本和产品(如医疗器械)的自由流通。在医疗器械领…

查找手机归属地轻松快捷,专业手机号码归属地数据源

在如今的信息社会中,手机已经成为了人们生活中不可或缺的一部分。当我们接到一个陌生的电话时,或者想了解一个电话号码的归属地时,我们可以借助一些工具来查找手机归属地。本文将介绍一种轻松快捷、专业的手机号码归属地数据源,并…

box-shadow属性的复合写法及高级用法,超详细!

前言:最近又叕看到了一个好看的特效,随后整理了一下,发现实现起来主要靠一个css属性就实现了,有一次刷新了我对css强大的认知😎,这个属性就是box-shadow,平常我们用到的比较少,但是针…

智慧工地视频汇聚管理平台:打造现代化工程管理的全新视界

一、方案背景 科技高速发展的今天,工地施工已发生翻天覆地的变化,传统工地管理模式很容易造成工地管理混乱、安全事故、数据延迟等问题,人力资源的不足也进一步加剧了监管不到位的局面,严重影响了施工进度质量和安全。 视频监控…

LLMs之Llama 3.1:Llama 3.1的简介、安装和使用方法、案例应用之详细攻略

LLMs之Llama 3.1:Llama 3.1的简介、安装和使用方法、案例应用之详细攻略 导读:2024年7月23日,Meta重磅推出Llama 3.1。本篇文章主要提到了Meta推出的Llama 3.1自然语言生成模型。 背景和痛点 >> 过去开源的大型语言模型在能力和性能上一…

C语言------指针讲解(3)

一、字符指针 在指针中,我们知道有一类指针类型为字符指针char*; int main() {char ch w;char* pc &ch;*pc w;return 0; } 还有一种使用方式如下: 上述代码中,本质是把hello的首字符的地址放到了pstr中。即把一个常量字符串的首字符…

netty使用redis发布订阅实现消息推送

netty使用redis发布订阅实现消息推送 场景 项目中需要给用户推送消息: 接口 RestController public class PushApi {Autowiredprivate PushService pushService;/*** 消息推送* param query* return*/PostMapping("/push/message")public String push(RequestBody…

国内访问Docker Hub慢问题解决方法

在国内访问Docker Hub时可能会遇到一些困难,但幸运的是,有多种解决方案可以帮助你顺利下载Docker镜像。以下是一些有效的解决方案: 配置Docker镜像源:你可以通过配置Docker的daemon.json文件来使用国内镜像源,比如DaoC…

四、GD32 MCU 常见外设介绍(8)SPI 模块介绍

串行外设接口(Serial Peripheral Interface,缩写为 SPI) 提供了基于SPI 协议的数据发送和接收功能, 可以工作于主机或从机模式。 SPI 接口支持具有硬件 CRC 计算和校验的全双工和单工模式。 8.1.SPI 基础知识 SPI 物理层 SPI接…

【Three.js基础学习】17.imported-models

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 前言 课程回顾: 如何在three.js 中引入不同的模型? 1. 格式 (不同的格式) https://en.wikipedia.org/wiki/List_of_file_form…

UART编程框架详解

1. UART介绍 UART:通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),简称串口。 调试:移植u-boot、内核时,主要使用串口查看打印信息 外接各种模块 1.1 硬件知识_UART硬件介绍 UART的全称是Unive…

Unity UGUI 之 事件接口

本文仅作学习笔记与交流,不作任何商业用途 本文包括但不限于unity官方手册,唐老狮,麦扣教程知识,引用会标记,如有不足还请斧正 本文在发布时间选用unity 2022.3.8稳定版本,请注意分别 1.什么是事件接口&…

找实习,三本计算机 > 985文科 ?

2018年3月,大三下学期。 写了一段时间博客以后,竟有人说要内推我。 我说我大三,还没毕业,准备暑假去找实习。 网上认识的朋友建议我去春招实习试试,还有些厂在走流程中,还有机会。 我婉拒了&#xff0c…

Centos 8 配置网络源

备份当前的软件源配置文件: sudo cp -a /etc/yum.repos.d /etc/yum.repos.d.bak 清理原有的 yum 仓库配置信息: sudo rm -f /etc/yum.repos.d/*.repo 获取阿里云的 CentOS 8 源配置: sudo curl -o /etc/yum.repos.d/CentOS-Base.repo ht…

Shell编程之正则表达式与文本处理器2--sed

目录 一、sed 工具 1. 概述 2. sed 原理 3、常用操作选项 3.1 常用选项 3.2 操作命令 4. sed 的使用 5. 具体操作 5.1 打印输出 p 5.1.1 显示范围、单行、指定行输出、指定往后加几行输出 5.1.2 显示奇偶行 5.1.3 将指定内容的行打印出来 5.1.4 只输出行号…

《python程序语言设计》第6章12题 显示字符,使用下面的函数头,编写一个打印字符的函数

def printChars(ch1, ch2, numberPerLine):a ord(ch1)b ord(ch2)count 0for i in range(a, b 1):count 1print(chr(i), end" ")if count % numberPerLine 0:print()printChars("1", "Z", 10)

UDP/TCP协议解析

我最近开了几个专栏,诚信互三! > |||《算法专栏》::刷题教程来自网站《代码随想录》。||| > |||《C专栏》::记录我学习C的经历,看完你一定会有收获。||| > |||《Linux专栏》&#xff1…

FTTransformer,一个很能打的模型

FTTransformer,是一个BERT模型架构在结构化数据集上的迁移变体。和BERT一样,它非常能打。 它可能是少数能够在大多数结构化数据集上取得超过或者匹配LightGBM结果的深度模型。 本范例我们将应用它在来对Covertype植被覆盖数据集进行一个多分类任务。 我们…

k8s通过应用修改yaml文件修改容器时区

通过挂载,把本地的/etc/localtime挂载到容器中: apiVersion: apps/v1 kind: Deployment metadata:name: seb-algorithmsnamespace: jiaoda spec:replicas: 1selector:matchLabels:app: seb-algorithmstemplate:metadata:labels:app: seb-algorithmsspec…