为什么很少见用 MessagePack 代替 JSON 的 Web 服务,不是更省流量吗?去一个 Discord 群问了 /t/932789 的问题,有个美国老外给我推荐这种方案。

2023-04-16 11:26:51 +08:00
 LLaMA
7752 次点击
所在节点    程序员
64 条回复
kaddusabagei38
2023-04-17 09:40:24 +08:00
这东西主要可能还是平台因素比较大...可能 cs 架构好一点,毕竟 client 本来什么东西都能自己选型,加个其他序列化库也没啥

bs 的话总感觉目前一切都是围绕着 json 去做的...搞这种东西可能成本太大了吧,f12 都不知道怎么去调试..
duke807
2023-04-17 09:46:41 +08:00
@icyalala
那是因为 msgpack 反序例化根本就不需要先整体解析 utf8 字串,因为 msgpack 本身就不是字符串格式

其中包含的一些字符串格式的内容,使用各环境自带的 utf8 编解码工具即可,譬如浏览器你怎么用 simdjson ?

至于你原本需要用 simdjson 的环境,你如果不满意现有 msgpack 库的 string 数据的转码速度,你直接把 utf8 转码函数替换一下就行了,搜 utf8 simd 库即可,会找到更多比 simdjson 更好的库,因为 utf8 的使用面可比 json 大多了,各环境的 utf8 编解码应该都已经用的就是 simd 加速过了的。


使用 msgpack 最大的好处是简单、扩展性好、通用性好,譬如要搞一个上传 图片 的 API ,和其它 API 一起共用一个 url 就行,而且除了 get/post 接口,还可以用于 websocket:

{ "user": "xxxxx", "auth": "tmp_password", "cmd": "upload_img", "image": 图片数据 }


我不是让后端费力开发一个小众接口,而是产品一开始就要选择简单、扩展性好、通用性好的 msgpack 。

至于它是否小众,你可以看一下其他坛友的回覆,很多大厂到在用。

互联网前后端不是最喜欢造轮子、脚手架和追新的吗?怎么到 msgpack 这样真正有意义的东西上,就各种排斥了呢?

当然如何选择是你的事,反正有人喜欢堆屎山也不会影响到我。
picone
2023-04-17 09:59:20 +08:00
@benrezzagmehamed #6 msgpack 不太可能比 proto 省,因为 msgpack 是自描述的,他还有字段名
serge001
2023-04-17 10:15:05 +08:00
@dayeye2006199 看场景,楼上已经说了单纯为了节省带宽,这样做不值得,并没有一耙子打死
Trim21
2023-04-17 10:17:45 +08:00
@dayeye2006199 但楼主的标题就是 web 服务啊...
cs8425
2023-04-17 10:45:21 +08:00
大概 6~7 年前用过
序列化反序列化的东西不是完全一致
忘了是结构层级变了还是型态变了
改成手搓格式二进制解决
后面也没遇到类似的需求就放置了
icyalala
2023-04-17 11:49:05 +08:00
@duke807 看来你不明白 simd 是怎么工作的。。simd 在处理较长数据时才会优势显著,如果你把字符串拆分出来,再用 simd 校验每个字符串,就会因为需要额外对齐或者数据过短无法向量化导致性能甚至会下降的。

回头再来看看我们讨论的适用场景:如果你是对外的服务提供者,无论是为前后端还是客户端,那明智的选择是尽可能为`更多人`服务,用 json 是毫无疑问的。所谓小众格式说的并非是没人用,而是 json 已经是事实标准、占据统治地位,其他格式的支持程序、系统生态根本不在一个量级上。

如果你是给自己的系统选择数据传输格式,追修更高读写性能和更小流量,那还有 flatbuffer 和 capn proto 等所谓 0 解码耗时的 zero-copy 方案。选择 msgpack 更多的是那些过去 json 带来的惯性,并不是什么追新。
duke807
2023-04-17 12:15:35 +08:00
@icyalala
跟你说 simd 是因为你在意这个
你可以试试 simdjson 和 msgpack ,看看到底哪个性能更好,用数据说话
对 msgpack 来说,我根本就不认为是个事,你非要拿 msgpack 不需要的东西来説事

如果是我提供服务,我会以 msgpack 为主做架构设计,单独外挂 json 给喜欢用 json 的人

至于生态,用 msgpack 是缺少什么了吗?你倒是说说呀

至于其它通讯格式,我当然知道它们的存在,我也知道它们是怎么死的,我一开始就不看好它们,无论是 xml 还是 protobuf

选择 msgpack 是因为它拥有 json 的绝大部份优点,保持简洁的同时,扩展性比 json 好很多,而且很类似,平替很方便
hengyunabc
2023-04-17 12:55:18 +08:00
我来说下根本原因吧,msgpack 是日本公司发明的,作者一并写了很多的库,比如 Fluentd ,但人力终有限,msgpack 的多语言实现也一般。当年 redis 作者推过一把。
本质上大部分后来的开源软件都要有商业公司背书,没有金钱的支持是玩不转的。
icyalala
2023-04-17 14:38:16 +08:00
@duke807
我没看出你对 simd 或者其他数据传输格式有了解。你非要数据那我就跑一下。
以最常见的 twitter.json 作为测试数据 https://github.com/simdjson/simdjson/tree/master/jsonexamples

体积:相差并不大
json: 467KB
msgpack: 402KB

在手头 M1 上跑 simdjson 和 msgpack-c 来解析,循环 16 次
simd:dom: 759MB/s
simd:ondemand: 1604MB/s
msgpack-c: 948MB/s
msgpack 并没有明显优势,而且也没验证 UTF-8 编码。
另外如果 simdjson 在现代 x86 上跑的更快。

json 缺点一大堆,唯一最大的优点就是人类可读写,msgpack 并没有继承这个优点。
lesismal
2023-04-17 15:06:38 +08:00
@icyalala
我不是挺 MessagePack ,我自己主业务也基本不用它。
但是单就性能而言,这里还是有个市场占有率的问题。因为 MessagePack 用户没那么多、像 #45 @hengyunabc 所说的,作者也没那么大精力和动力去做更大的性能优化。如果很多很多人用,MessagePack 的性能应该是可以做到比 simdjson 更强的,因为需要处理的字节数、逻辑肯定是比 json 少一点的,simd 指令能用来优化优化 json 也可以用于 MessagePack ,比如 simdjson 作者去实现 MessagePack 。

> 也没验证 UTF-8 编码

MessagePack 本来就是二进制,当然是不需要验证 utf8 的,主要还是 simd 针对性优化太强。


@duke807
> 至于其它通讯格式,我当然知道它们的存在,我也知道它们是怎么死的,我一开始就不看好它们,无论是 xml 还是 protobuf

xml 没死,protobuf 更是没死,只是 web 领域用的人少罢了。大规模服务集群之间的 RPC ,pb 占有率还是很高的,游戏行业 pb 的占有率也非常高。


一些传统 c/cpp 领域,不涉及深拷贝的,就是 c struct 1 字节对齐,直接 struct 地址拷贝传输,性能和 buffer size 都是无敌的。

二位没必要争执这些,http1x 性能和流量浪费都那么垃圾也照样统治着互联网。技术栈的市占率都是历史综合因素造成的,自己家的业务选择自己认为适合的、自己喜欢的就行了。
lesismal
2023-04-17 15:20:50 +08:00
@icyalala
> 体积:相差并不大
> json: 467KB
> msgpack: 402KB
> 在手头 M1 上跑 simdjson 和 msgpack-c 来解析,循环 16 次
> simd:dom: 759MB/s
> simd:ondemand: 1604MB/s
> msgpack-c: 948MB/s

另外,这种性能对比是存在一些不合理的:
1. 是应该对比相同结构的序列化反序列化次数,而不是对比每秒处理了多少 MB/GB
2. 这种 size 的结构已经是非常大了,实际的业务中,单个消息体这么大的时候应该是少数场景。所以也应该考虑常规 size 的结构的压测对比,我对 simd 指令没做过什么研究,随便搜了一段:
lesismal
2023-04-17 15:22:54 +08:00
上一楼手滑发布了,接#52

SIMD 的优点?我们普通应用场景中有很多情况下需要对大量数据执行相同的操作,例如图片处理、视频特效等,在这种时候使用 SIMD 指令能取得很大的性能提升。例如 SSE 指令,支持每次对 4 个 FP32 进行操作,那么我们常用的 Vector4 向量加减乘除,皆可使用一个指令完成,效率大大提高。

SIMD 的缺点?有得必有失,为 SIMD 优化的程序在处理分支指令时性能不佳,因为分支指令本质上是一部分数据流根据条件去执行不同的指令,当多个数据流需要运行的分支不同时,需要运行两次程序遍历来完成所有数据流的操作。此外,不是所有情况下都需要很高的并行度,典型例子就是 AVX512 指令。虽然理论上一次能处理 16 个 FP32 ,但很难遇到需要同时处理这么多数据的场景。常见的向量、矩阵计算,操作单位都是 Vector4 ,要适配 AVX512 就需要大改程序流程和算法,去把好几个数凑起来一起操作,边际效应明显。而且在前几代 CPU 上 AVX512 还有降频问题,一跑起来频率上不去,速度还不一定有 SSE 快。

所以,常规主流业务的普通 size 结构场景下,simd 是否还有优势?

3. simdjson 和 MessagePack c 编译优化是如何的,比如都是 O1 还是 O2 还是 O3 ,实际场景允许到 O3 不?
cloudyplain
2023-04-17 16:38:13 +08:00
对于 java 来说 msgpack 官方实现,除了体积有优势(未压缩),jackson-json 性能都比他要好不少(schema-less 场景),jackson 本上有很多性能优化,jackson 支持的二进制 format 比如 cbor 、smile 都比它性能要好。
Nazz
2023-04-17 16:49:28 +08:00
@lesismal MessagePack 的主要优势还是在于描述二进制数据而不是性能. JSON 已经成为了 Web IDL 的事实标准, 有大量的公司和个人提供优化, 不仅仅是 SIMD, 还有 JIT, ASM.
lesismal
2023-04-17 17:00:45 +08:00
@Nazz 你没看懂我意思,我说的不是现有的 MessagePack 实现性能有优势

#51
但是单就性能而言,这里还是有个市场占有率的问题。因为 MessagePack 用户没那么多、像 #45 @hengyunabc 所说的,作者也没那么大精力和动力去做更大的性能优化。如果很多很多人用,MessagePack 的性能应该是可以做到比 simdjson 更强的,因为需要处理的字节数、逻辑肯定是比 json 少一点的,simd 指令能用来优化优化 json 也可以用于 MessagePack ,比如 simdjson 作者去实现 MessagePack 。
swulling
2023-04-17 17:31:15 +08:00
看看 OpenAI 的 stream 返回,什么流量,不重要。
icyalala
2023-04-17 18:27:37 +08:00
@lesismal 先回复几个问题:

我提 UTF-8 校验说的是 string 类型的值,内部编码是 UTF-8 ,如果为了安全考虑是要做校验的。json 可以预先整个输入都校验一遍,而二进制格式需要解析出来每个 string 值之后再一一校验,不是说二进制就不考虑校验了。

simd 的支持现在都是动态派发的,就是运行时检测一次 cpuid 判断指令集,avx512 进几代 CPU 都是不降频的,不降频时才会用 avx512 ,否则还是 avx256 或继续降级,所以这个不用担心。没有 UB 的代码一般 O3 没问题,即使 O2 也相差不大。但这些都是细节,不重要。json/msgspec 性能对比其实也只能这样简单搞搞,实际应用里如果要转为用户定义的结构或者对象,耗时大头其实是在对象创建上。真要是自己用的服务又在乎性能,在 C/C++ 应用里 flatbuffer 和 capnproto 更合适,至少比自己 struct 序列化要靠谱,现在很多游戏也在用。

我认同你的后面的观点,这是市场占有率的问题。一个标准即使性能上烂,但流行到这种地步就会有越来越多的高手投入到这里来,做性能优化、做生态支持。但是一个标准用的人少,即使设计优秀,也很难吸引足够人才投入其中。
lesismal
2023-04-17 19:00:28 +08:00
@icyalala
对,大家基本观点是一致的。

string 在传统语言里的设计也是不太友好,支持二进制通用才更舒服,但也确实省了一点标识头。

capnproto 好久以前看到官方自己的数据非常牛,但这个我一直没在自己项目里用过,你们实际项目有用到不?好用不?
duke807
2023-04-17 19:38:05 +08:00
@icyalala 辛苦了

我不觉得 json 的人类可读可写能算多大的优点
举例:doc 文档的裸数据不需要人类可读可写,但依然可以很方便的人工读写

设计产品架构的时候,以 msgpack 为主,可以不受 json 不能传输二进制的限制,可以设计出更简洁的 api 接口

如果是 json ,要传二进制,要纠结用 base64 还是 单独开一个 api ,单独开 api 的话用户验证又要单独搞一套机制,url 也要搞老长一串

而且要先上传文件,再在 json 里面填文件 url 地址,对方收到 json 之后,又要单独下载这些文件,很多时候都是些不大不小的文件

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/932879

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX