科普一个冷门的,但是很强的技术:MessagePack,简称msgpack。msgpack不是软件,是一个标准,可以先把它看成二进制的json,“二进制json”容易让人联想到一个更流行一点的标准:BSON。如果你不知道bson是啥可以去查一下,总之msgpack和bson是同类型的竞争产品,但是msgpack无论从速度还是体积上都秒杀bson,至少在网络传输上是这样的。
json都知道是啥吧,在序列化领域神一般的存在。什么是序列化呢,其实就是降维打击:任何多维的数据对象都必须被降维打击成一维才能进行存储和网络传输。
msgpack也是一个降维打击,哦不,序列化的手段,只不过它序列化的结果是二进制格式而非json的文本格式,不理解的可以类比http1.1和http2.0,就是一个由文本格式进化到二进制格式的例子。
这种进化有什么好处以后专门写一篇文章谈谈,题目暂定《从字符时代到二进制时代》。本文谈谈msgpack有什么好处,为啥说它能取代json?
首先按官方的话说,msgpack比json小,比json快。比json小是一定的,官网上有一个例子:
上面那个json串在utf8编码下每个字符一个字节,总共27字节,转换成msgpack格式之后只剩下18字节,压缩了三分之一。之所以msgpack能够压缩是因为json串本身有许多没用的信息,比如每一个key的双引号就可以省去,简单的Boolean类型非要用四五个字节来表示(true和false)。当然XML的没用信息就更多了,这些都是文本格式本身的弊端,二进制格式就是来解决这些问题的,比如数字就是数字,就应该用二进制表示。
变长实数
msgpack对实数类型的一个特色是可变长的实数类型,以至于128以下的正整数都可以用1个字节表示!如果说bson编码在某些情况下回比json还大,那msgpack在任何情况下都比json小,最坏的情况下比如10以内的正整数,压缩率才是100%,比如:(但即使这样msgpack的速度还快)
事实上msgpack提供10种不同长度的整数,通过不同的前缀来区分类别,这样如果仅存储一个人的年龄的话就不必浪费64位浮点数的奢侈空间了,这就是前缀编码的魅力。具体可以去看看它的spec:
https://github.com/msgpack/msgpack/blob/master/spec.md
然后msgpack比json快就不用说了,json本身的编译就需要更多的时间,尤其是10进制实数和二进制数之间的转化。msgpack之所以比json又快又好,是因为:
msgpack遵循最优编码
最优编码也叫Huffman编码,什么是最优编码呢,用我自己的话说就是,没有浪费一丁点信息。那什么样的编码会浪费信息呢?定长编码就容易浪费信息,举一个例子,设计这样一套编码,每一种数据由1字节的类型段和多字节的数据段组成(类型字段暗示了数据字段的长度),然后线性排列(序列化),其中1个字节所表示的256种类型必须全部用到才不会造成浪费,否则剩下的必须作为“保留类型”才说得过去。
如果我们真的不需要那么多种数据类型,甚至100种都用之不尽,那么可以对剩下的156种数据类型做“长度压缩”。
如图,怎么办?Huffman编码告诉我们可以将这棵完全二叉树的右半部分收敛成度为2的叶子,变成更优的二叉树:
如图,第五种类型是最短的,应当留给使用频率最高的数据类型。
但这还不是最优二叉树,最优树还要更具每种类型出现的频率来考虑树的长势。msgpack就是按这个思想来绘制自己的最优二叉树的。但是当我用百度脑图将msgpack的最优树画出来以后发现它好像并没有严格按照Huffman树的画法,而是有些任性:
图中,37种数据类型中居然有32个类型都是8个bit前缀,全部挂载在“110”之后。当然,也许是为了硬件考虑,也许数据类型真的的不好按照使用频率来排序。总之msgpack采用huffman来编码是非常有眼光的。
Message Pack VS JSON
既然msgpack比json又小又快,json真的一无是处吗?虽然在网络传输的应用场景上msgpack可以完胜json,可作为配置文件的场景上又如何呢?我们知道JSON格式对用户是很友好的,可读性非常强,在编辑器中代码折叠,类型高亮都非常方便。msgpack作为二进制格式似乎不好直接编辑。
naive!
为什么不能图形化编辑二进制文件呢?灵感来自json-editor(json图形化编辑器)项目:https://jimmy.blog.csdn.net/article/details/87446545
由于现在msgpack还不流行,msgpack-editor项目还不存在,如果你感兴趣可以先把它做出来,这样一来就可以愉快的编辑二进制的配置文件了,图形化编辑器比文本编辑器更友好,不仅可以提供很多快捷功能还能有效的查错。
经过本文的分析,message pack在各个领域都可以完胜json,取代后者只是时间问题。
取名吐槽
唯一感到美中不足的是,message pack这个名字取得不太满意,不够具有吸引力,不像BSON那样“霸道”和简短。如果我来开发,我会叫他Huffman Pack或者Huffman serializator之类的名字。
(完)
【日记】
CSDN的“公众号同步文章”功能成功将文章中的图片外包到腾讯的服务器上了,比如一个图片链接:
https://ss.csdn.net/p?https://mmbiz.qpic.cn/mmbiz_jpg/MpRDliazuVE2YeichQVupFG1joUB7PxEC3F4VHwc1SGsNwgMLaKNtZsGdX73crmTWcoR0xFyrukicJmuAln3CqwWA/640?wx_fmt=jpeg
看上去是来自csdn.net,仔细一看url后面跟着另一个url,其实图片数据来自qpic.cn,只是从csdb.net反向代理了一下,其实CSDN可以将真实的url稍微编码一下,变成乱码就看不出来这种操作了🙂