Google协议缓冲区与ASN.1相比如何?
Google协议缓冲区和ASN.1(使用PER编码)最显着的区别是什么?对于我的项目来说,最重要的问题是序列化数据的大小。有没有人在两者之间做过任何数据大小的比较?Google协议缓冲区与ASN.1相比如何?
自从我完成了任何ASN.1工作以来,这已经很长时间了,但其大小很可能取决于您的类型和实际数据的细节。
我会强烈建议您原型,并把一些真实的数据进行比较。
如果您的协议缓冲区包含重复的原始类型,您应该查看Subversion协议缓冲区中的最新源代码 - 它们可以用现在更加节省空间的“打包”格式表示。 (我的C#端口有只是赶上了这个功能,上周一些时间。)
如果使用ASN.1与非对齐PER,并确定使用相应的约束(数据类型例如,指定下/上整数的范围,列表长度的上限等),您的编码将非常紧凑。对于字段之间的对齐或填充等内容,将不会浪费比特,并且每个字段都将被编码为保持其允许的值范围所需的最小比特数。例如,INTEGER(1..8)类型的字段将被编码为3位(1 ='000',2 ='001',...,8 ='111');而一个有四种选择的CHOICE将占用2位(表示所选择的选择)加上所选备选项占用的位。 ASN.1还有许多其他有趣的功能,已经在许多已发布的标准中成功使用。一个例子是扩展标记(“...”),当它应用于SEQUENCE,CHOICE,ENUMERATED和其他类型时,实现了实现不同版本规范的端点之间的向前和向后兼容性。
当打包/编码消息的大小是很重要的,你也应该注意一个事实,即protobuf的无法收拾repeated
字段是一个primitive numeric type
的不是,read this以获取更多信息。
这是一个问题,例如如果有该类型的消息:(评论定义值的实际范围)
message P{
required sint32 x = 1; // -0x1ffff to 0x20000
required sint32 y = 2; // -0x1ffff to 0x20000
required sint32 z = 3; // -0x319c to 0x3200
}
message Array{
repeated P ps = 1;
optional uint32 somemoredata = 2;
}
如果你有阵列的长度,例如,32比你会导致大约250到450个字节的填充消息大小与protobuf,取决于数组实际包含的值。如果您使用int32
而不是sint32
并且具有负值,那么在使用完整32位范围或的情况下,这甚至可以增加到超过1000字节。
原始数据blob(假定Z可以定义为int16
值)将只消耗320个字节,因此ASN.1消息是总是小于320字节,因为最大值实际上不是32位,但19位(x,y)和15位(z)。
的protobuf的消息大小可以与该消息定义进行优化:
message Ps{
repeated sint32 xs = 1 [packed=true];
repeated sint32 ys = 2 [packed=true];
repeated sint32 zs = 3 [packed=true];
}
message Array{
required Ps ps = 1;
optional uint32 somemoredata = 2;
}
这导致消息大小约100字节之间(所有的值都是零),300字节(在范围内的最高值),500字节(所有值都是高32位值)。
也许是一个相关的问题:当我们已经有一个成熟的ASN.1时,为什么我们需要协议缓冲区? Google没有在这里发明综合征? – 2018-03-05 09:58:50