Shape Security开源了一个新的无模式二进制序列化格式,名为SuperPack。
SuperPack使用了二进制的序列化模式,这意味着会减少负载的大小。按照Shape Security的说法,对于一个给定的4.48 KB的样例信息,相对于多个其他的无模式格式,SuperPack的负载是最小的:
YAML和BSON非常冗长,会增加消息的负载。JSON比YAML要好得多,但是因为它基于文本编码格式,所以它的大小依然会远远超过SuperPack。在gzip压缩之后,它们的值会出现比较大的差异,YAML、JSON和SuperPack的值非常接近,是原始消息的12-14%。
采用SuperPack编码格式的一个主要优势在于,与客户端通信的时候不需要预先交换消息的模式。数据类型的信息会包含在负载之中。SuperPack有36个预先定义的数据类型,包括常见的true、false、uint16、uint32、float32,也包括不那么常见的类型,如 uint6、nint4和array5等,这些类型能够代表消息中很可能出现的值。
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是开源的,并且采用了非常宽容的许可证协议。
文章转载自 开源中国社区[http://www.oschina.net]