SuperPack——实现更小负载的新序列化格式

阅读数:1061 2016 年 9 月 1 日

话题:JavaScript语言 & 开发

Shape Security开源了一个新的无模式二进制序列化格式,名为SuperPack

SuperPack 使用了二进制的序列化模式,这意味着会减少负载的大小。按照 Shape Security 的说法,对于一个给定的 4.48 KB 的样例信息,相对于多个其他的无模式格式,SuperPack 的负载是最小的:

  原始信息 YAML BSON

JSON Sereal SuperPack
非压缩 4.769 B 134% 111% 69% 40% 28%
压缩 4.769 B 14% 20% 12% 16% 13%

YAML 和 BSON 非常冗长,会增加消息的负载。JSON 比 YAML 要好得多,但是因为它基于文本编码格式,所以它的大小依然会远远超过 SuperPack。在gzip压缩之后,它们的值会出现比较大的差异,YAML、JSON 和 SuperPack 的值非常接近,是原始消息的 12-14%。

采用 SuperPack 编码格式的一个主要优势在于,与客户端通信的时候不需要预先交换消息的模式。数据类型的信息会包含在负载之中。SuperPack 有 36 个预先定义的数据类型,包括常见的true、false、uint16、uint32、float32,也包括不那么常见的类型,如 uint6nint4array5等,这些类型能够代表消息中很可能出现的值。

SuperPack 还包含了针对数组、字符串以及 map 的类型。其中还有个类型是 extension,它能够让用户添加新的类型。SuperPack 还有两个可选的优化选项,能够减少特定场景下的负载:重复字符串优化(repeated string optimization)以及重复 keyset 优化(repeated keyset optimization)

我们采访到了 Michael Ficarra,他是一名研究工程师和自由 / 开源软件协调人员(FOSS Coordinator),了解到了 SuperPack 的更多细节。

InfoQ:在编码后,你们的负载会更小,相对于其他的无模式格式,你们的做法有何不同呢?

MF: SuperPack 有其背后的哲学,那就是即便我们不能预先推测出数据的模式,但数据中的结构或值很可能会重复出现很多次。举个例子,假设有个名为“cats”的数据结构,它将每个人与他的猫关联在了一起。我们不是直接进行编码,考虑到每只猫都有名称、生日以及喜欢的食物,我们只对其编码一次,稍后会对其进行引用,对这些值采用了非常高效的 protobuff 风格的打包方式。

另外,有些值比其他的值更为通用,应该有更为高效的表述形式。如果你看一下格式的详细描述的话,你会发现所有的值都由一个单字节的指示符打头,它用来表明值的类型,我们将其称之为“类型标签(type tag)”。在类型标签域中,我们预留了一部分区域范围,这样的话,值的全部或部分内容就可以在标签本身中进行编码。举个简单的例子,有两个 boolean 类型标签:一个用于值 true,另一个用于值 false。类似的,还有 64 个“uint6”类型标签,允许我们使用一个字节就能表示 0 到 63 之间的每个数字,另外,对于条目长度小于 32 的数组(必须要同时对它的长度和条目进行编码),可以将它的长度编码到标签中。回到前面的例子中,猫的胡须通常不会多于 64 根并且大多数人所养的猫不会超过 32 只,因此这些值能够非常高效地进行存储。

InfoQ:你们将 SuperPack 与模式驱动的二进制格式进行过对比吗,比如 Protocol Buffers?Protobuf 的负载会明显更小吗?

MF:我们没有进行过这种类型的对比。我认为,在大多数场景下,Protobuf 的负载会更小,除非 SuperPack 的字符串去重功能能够特别有效。当你的需求允许你使用模式驱动格式的话,尤其是能够与某种无损数据压缩算法(如 LZW 或 Deflate)结合使用时,那么你就应该采用这种方案。

InfoQ:在消息的编码 / 解码上所消耗的时间是怎样的?

MF:根据编码器是否启用可选的 keyset 和字符串去重优化功能,编码时间会有所差异。在实现语言层面,也会有一些遗留的性能难题,比如 JavaScript 针对所有的数字都使用了 IEEE 754 的双精度形式。

InfoQ:你们有支持其他语言的计划吗?

MF:当然!我们已经有了一个 Java 实现,目前,这个实现我们在 Shape Security 内部使用。它还没有为开源做好准备,但是如果我们听到有这种需求的话,就会加快这一进程。如果社区希望为另外的生态系统启动新实现的话,我也是非常乐意提供帮助的。我觉得 Rust 实现将是非常令人兴奋的!

另外,值得一提的是,SuperPack 依然非常年轻,如果读者对于它的提升有什么建议的话,我们非常乐意倾听,只需在规范的 issue tracker上开启一个 issue 即可。我们希望将来版本的 SuperPack 会更棒!

目前,SuperPack 自带了一个 JavaScript 转码器,但是其他的转码器可以基于它来进行开发。SuperPack 是开源的,并且采用了非常宽容的许可证协议

查看英文原文SuperPack, a New Serialization Format with a Smaller Payload