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

devtools/2024/9/23 21:18:26/

先说结论

从易用性、性能、内存占用、编码后大小等几个方面综合考虑 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://www.ppmy.cn/devtools/85443.html

相关文章

python拼接字符串方法

文章目录 1. 使用加号()2. 使用str.join()方法3. 使用格式化字符串(f-strings, % 操作符, .format() 方法)4. 使用列表推导式和join()结合 性能对比 在Python中,字符串拼接是将两个或多个字符串合并成一个新字符串的过…

WPF的前世今生

WPF发展现状简述 WPF,作为微软推出的用于构建Windows客户端应用程序的UI框架,自2006年推出以来,已经成为开发者构建富交互式用户界面的首选技术之一。随着技术的不断迭代,WPF以其强大的数据绑定、样式和模板功能,以及对…

《Single-Stage Extensive Semantic Fusion for multi-modal sarcasm detection》

系列论文研读目录 文章目录 系列论文研读目录文章题目含义ABSTRACTKeywords1. Introduction2. Related work3. Method3.1. Multi-modal projection 多模态投影3.2. Extensive Semantic Fusion Multiway Transformer 可拓语义融合多路Transformer3.3. Multi-objective optimizat…

JAVA同城服务场馆门店预约系统支持H5小程序APP源码程序

🔥同城服务场馆门店预约系统:一键预约,便捷生活新体验!🎉 🌟告别排队等待,预约新风尚🌟 你还在为去游泳馆、健身房或是瑜伽馆排队等待而烦恼吗?同城服务场馆门店预约系统…

学习测试13-车载测试

车的发展 1,动力 VCU 是实现整车控制决策的核心电子控制单元 汽车驱动控制:车都是有VCU发出,驱动控制,电池,电机都是执行器。比如: 汽车启动:启动,发车,VCU发送指令到齿轮这些,开始转动启动&a…

Redis备份策略面试三道题

关于Redis备份策略的面试题,由简单到困难,可以给出以下三道题目及其参考答案: 1. 简单题:Redis支持哪些主要的备份方式? 参考答案: Redis支持两种主要的备份方式: RDB(Redis Data…

一下午连续故障两次,谁把我们接口堵死了?!

唉。。。 大家好,我是程序员鱼皮。又来跟着鱼皮学习线上事故的处理经验了喔! 事故现场 周一下午,我们的 编程导航网站 连续出现了两次故障,每次持续半小时左右,现象是用户无法正常加载网站,一直转圈圈。 …

云原生周刊:Kubernetes v1.31 中的移除和主要变更|2024.7.22

开源项目 Argo Rollouts Argo Rollouts 是一个 Kubernetes 控制器和一组自定义资源定义(CRDs),提供高级部署功能,例如蓝绿部署、金丝雀部署、金丝雀分析、实验以及渐进式交付功能给 Kubernetes。 Argo Rollouts 可选地集成了 I…