MessagePack简介

It’s like JSON. but fast and small.

MessagePack是什么

MessagePack是一个高效的二进制序列化格式,它像JSON一样支持不同语言间的数据交互,但是它的性能更快,序列化之后的码流也更小。

比如小的整型会被编码为一个单字节,短字符串也仅仅需要额外的一个字节来编码。

我们可以看下面的例子说明:

实际上MessagePack确实就“像JSON”一样。

性能如何

序列化的性能体现可以分为两方面,一个是编码效率,一个是编码速度。

根据网友的测试数据,编码效率上确实是比JSON要好的,很明显因为MessagePack本身就是在JSON基础上进行字典编码。但经过gzip压缩后,实际差别不大。所以对于能叠加gzip压缩的场景(比如HTTP协议),显然使用MessagePack的必要性也不高。

Format Encoded (bytes) Encoded + Gzipped (bytes)
JSON 143025 26214
MessagePack 120799 (-22226) 26074 (-140)

而编码速度上,编解码时间相差70%以上,在循环10k次以上时间感知上体现比较明显,但常见情境下比如100次循环的条件下,差异在50ms级别。

Loops JSON Encoding (s) MessagePack Encoding (s) JSON Decoding (s) MessagePack Decoding (s)
1 0.00064 0.00019 (-0,00045) 0.00164 0.00051 (-0,00113)
10 0.00340 0.00082 (-0,00258) 0.00866 0.00194 (-0,00672)
100 0.03135 0.00732 (-0,02403) 0.07905 0.01700 (-0,06205)
1000 0.30385 0.07250 (-0,23135) 0.77422 0.16785 (-0,60637)
10000 3.02723 0.72503 (-2,95472) 7.74523 1.65804 (-6,08719)
100000 30.29353 7.25324 (-23,04029) 77.48423 16.71792 (-60,76631)

因此综上,在HTTP协议下传输的话,切换到MessagePack的必要性不大。但在自定义协议上还是可以尝试使用的,不经过压缩编码,在流量方面比JSON要优化一些,编码效率也高,尤其你是想使用一个相对不那么可读的序列化编码。

对比ProtoBuf

其实根据官网的时间MessagePack应该在2008年就问世了,但到如今应用的范围并不算广泛。而同年Google也正式对外发布ProtoBuf 2.0。在数据二进制编码序列化上,ProtoBuf的使用率更高。在gRPC继续推广的过程中,ProtoBuf可能有更多的应用。

ProtoBuf二进制编码,通过T-(L)-V(TAG-LENGTH-VALUE)方式编码,因为对字段使用编号指代,所以编解码依赖proto文件,编码后数据没有可读性。公开发布时,ProtoBuf规范版本是proto2,目前ProtoBuf规范的版本是proto3。官方文档可见此处。编解码过程的示例也可以参考此文

ProtoBuf更容易拓展,尽管编解码端需要统一使用proto消息规范文件。同时因为Protobuf IDL统一了语言无关的服务定义,协议部分可以独立,对于多端接口的定义也是一种约束。Google在开发ProtoBuf时首先考虑的也并不只是编解码效率问题。并且消息协议变更时,可以平滑升级,这对于二进制编码的协议而言是非常重要的。

相比而言MessagePack就是比较简单独立的了,既然理解为经过优化的JSON,就没有消息规范文件的约束。

编码规范介绍

MessagePack目前已经支持了常见的的编程语言。如果你要开发新的编解码器,是需要了解序列化编码规范的。

编码规范可以参见MessagePack在github的文档

序列化过程中会根据首字节(及后续字节)来确定编码格式,比如常见的一些首字节:

格式 首字节 (in binary) 首字节 (in hex)
正整数(特定) 0xxxxxxx 0x00 - 0x7f
fixmap 1000xxxx 0x80 - 0x8f
fixarray 1001xxxx 0x90 - 0x9f
fixstr 101xxxxx 0xa0 - 0xbf
nil 11000000 0xc0
(never used) 11000001 0xc1
false 11000010 0xc2
true 11000011 0xc3

浮点数编码格式:

1
2
3
4
5
6
7
8
9
float 32 stores a floating point number in IEEE 754 single precision floating point number format:
+--------+--------+--------+--------+--------+
| 0xca |XXXXXXXX|XXXXXXXX|XXXXXXXX|XXXXXXXX|
+--------+--------+--------+--------+--------+

float 64 stores a floating point number in IEEE 754 double precision floating point number format:
+--------+--------+--------+--------+--------+--------+--------+--------+--------+
| 0xcb |YYYYYYYY|YYYYYYYY|YYYYYYYY|YYYYYYYY|YYYYYYYY|YYYYYYYY|YYYYYYYY|YYYYYYYY|
+--------+--------+--------+--------+--------+--------+--------+--------+--------+

IEEE 754单/双精度格式。

字符串编码格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
fixstr stores a byte array whose length is upto 31 bytes:
+--------+========+
|101XXXXX| data |
+--------+========+

str 8 stores a byte array whose length is upto (2^8)-1 bytes:
+--------+--------+========+
| 0xd9 |YYYYYYYY| data |
+--------+--------+========+

str 16 stores a byte array whose length is upto (2^16)-1 bytes:
+--------+--------+--------+========+
| 0xda |ZZZZZZZZ|ZZZZZZZZ| data |
+--------+--------+--------+========+

str 32 stores a byte array whose length is upto (2^32)-1 bytes:
+--------+--------+--------+--------+--------+========+
| 0xdb |AAAAAAAA|AAAAAAAA|AAAAAAAA|AAAAAAAA| data |
+--------+--------+--------+--------+--------+========+

其中XXXX或YYYY、ZZZZ都是表征字符串数据data大小N的预留位,大端序。

数组的编码格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
fixarray stores an array whose length is upto 15 elements:
+--------+~~~~~~~~~~~~~~~~~+
|1001XXXX| N objects |
+--------+~~~~~~~~~~~~~~~~~+

array 16 stores an array whose length is upto (2^16)-1 elements:
+--------+--------+--------+~~~~~~~~~~~~~~~~~+
| 0xdc |YYYYYYYY|YYYYYYYY| N objects |
+--------+--------+--------+~~~~~~~~~~~~~~~~~+

array 32 stores an array whose length is upto (2^32)-1 elements:
+--------+--------+--------+--------+--------+~~~~~~~~~~~~~~~~~+
| 0xdd |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ| N objects |
+--------+--------+--------+--------+--------+~~~~~~~~~~~~~~~~~+

其中的XXXX或YYYY、ZZZZ都是表征数组大小N的预留位。

Comments