Google Protocol Buffers 和 ASN.1(使用 PER 编码)之间最显着的区别是什么?对于我的项目来说,最重要的问题是序列化数据的大小。有人对两者之间的数据大小进行过比较吗?

有帮助吗?

解决方案

这是一个漫长的时间,因为我做了任何ASN.1工作,但规模很可能取决于你的类型和实际数据的详细信息。

我的强烈的建议,你既原型,并把一些真实的数据进行比较。

如果您的协议缓冲区将包含重复的基本类型,你应该看看在Subversion的最新源Protocol Buffers的 - 他们可以在一个“打包”现在的格式来表示这是更节省空间的。 (我的C#端口具有的只是的赶上了这个功能,上周一些时间。)

其他提示

如果您将 ASN.1 与 Unaligned PER 结合使用,并使用适当的约束定义数据类型(例如,指定整数的下限/上限、列表长度的上限等),您的编码将非常紧凑。字段之间的对齐或填充等操作不会浪费任何位,并且每个字段都将以保存其允许的值范围所需的最小位数进行编码。例如,类型为 INTEGER (1..8) 的字段将被编码为 3 位 (1='000', 2='001', ..., 8='111');具有四个选项的 CHOICE 将占用 2 位(指示所选选项)加上所选选项占用的位。ASN.1 还有许多其他有趣的功能,这些功能已成功用于许多已发布的标准中。一个例子是扩展标记(“...”),当将其应用于 SEQUENCE、CHOICE、ENUMERATED 和其他类型时,可以实现实现不同版本规范的端点之间的向后和向前兼容性。

当打包/编码消息的大小很重要时,您还应该注意 protobuf 无法打包的事实 repeated 不属于 a 的字段 primitive numeric type, 读这个 了解更多信息。

这是一个问题,例如如果您有该类型的消息:(注释定义了值的实际范围)

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,则使用 protobuf 会产生大约 250 到 450 字节的打包消息大小,具体取决于数组实际包含的值。如果您使用完整的 32 位范围,这甚至可以增加到超过 1000 个字节 或者 如果你使用 int32 代替 sint32 并有负值。

原始数据 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 位值)之间。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top