【问题标题】:Encoding, datatypes & packed repeated fields编码、数据类型和打包的重复字段
【发布时间】:2012-02-06 13:16:15
【问题描述】:

我对打包字段和存储/序列化有一些疑问 带有协议缓冲区的数据。 我本质上想要做的是将 4MB 的数据存储到一个文件中。

我拥有的数据(在我们的嵌入式系统中)以 uint8_t(一个字节)的形式接收,我希望尽可能高效地存储这些数据。

我一直在测试各种 protobuf 设置(四个);

repeated uint32_t datastruct = 1;
repeated uint32_t datastruct = 1 [packed = true]

将两个变体分配为 1 比 1(将 uint8 放入 uint32),并且两个变体都以 4 个值移位到 uint32_t。

令我惊讶的是,存储的文件比原始文件大得多 数据。 (当然,我将 uint8 放入 uint32 的示例是预期的..) 我能达到的最好结果是 5.2MB 的 4MB 数据, 真的不是很好。

我在这里误解了一些重要的事情吗? 我确实意识到 protobuf 将信息添加到数据包中,但是 25% 增加太多恕我直言。

同时使用 GzipOutputStream 会增加而不是减小文件的大小。

任何提示将不胜感激!

感谢您的宝贵时间。

【问题讨论】:

  • 这里的uint32_t 是什么?那是 .proto 中的 message 吗?
  • 是的,就是这样。
  • 那么......我很困惑......我认为“打包”甚至工作这样......?还是一个团体?
  • 引用文档:Only repeated fields of primitive numeric types (types which use the varint, 32-bit, or 64-bit wire types) can be declared "packed". - 据我所知,如果uint32_tmessage,则使用“packed”是无效
  • 我意识到我在这里有点不清楚,在 protofile 中定义了以下内容:repeated uint32 datafield = 1 [packed = true];我与此消息一起使用的数据类型是 uint32_t 类型(当然还有 32 位)。

标签: c++ serialization protocol-buffers


【解决方案1】:

此答案基于您在 .proto 术语中使用 uint32 的假设:

packed 在这里是积极的(删除每个值的标题);但是,通过将单个 uint8 打包到 uint32 中,您将遇到“varint”编码的一个方面 - 具体而言,如果设置了字节的最高有效位,它将占用 2 个字节(varint 每个字节使用 7 位数据,以及一位作为延续)。因此,我建议切换到 bytes 类型,它代表任意字节块,并且“按原样”编码,没有任何 varint 或类似内容。它不会被重复/打包 - 只是:

[required|optional] bytes data = 1;

另一种选择是使用fixed32(重复和打包),并为每个值放置(通过移位)4 个字节,但是当您完成此操作时,您不妨转到bytes 并拥有一个更明显的 1:1 地图。

重新压缩; gzip 在没有很多重复块的情况下增加任意二进制文件的大小并不少见。相比之下,如果您的 protobuf 文档包含字符串,则大小通常会缩小,因为 gzip 可以发现重复的块。

【讨论】:

  • 7 位数据和 1 位继续。
  • 在使用 bytes 数据类型进行测试时,消耗的空间比传入的数据略多。一旦数据中出现模式,使用 gzip 压缩 protobuf 消息消耗的空间就会急剧减少。
  • @almagest 是的,根据我对 Mike 的回答的评论,将 4MB 的 blob 存储为字段 1 需要 5 字节的开销
【解决方案2】:

如果要存储字节序列,请使用 bytes 数据类型。开销会很小。

您从int32 看到的额外开销来自可变长度编码;数字以每个字节7位存储,第8位表示是否还有更多。所以一个满量程的 32 位值需要 5 个字节来存储。有一个fixed32 类型,每个值总是占用 32 位(4 字节) - 如果大多数值需要 32 位来表示,效率会更高,而如果大多数值都很小,效率会更低。

【讨论】:

  • 具体来说,开销(对于字段#1,如图所示)将是 1 字节的标头和 4 字节来表示 4MB 的长度为“varint”
猜你喜欢
  • 2019-01-21
  • 2010-12-04
  • 2017-09-16
  • 2012-06-24
  • 2018-07-27
  • 2019-06-04
  • 1970-01-01
  • 2023-01-25
  • 2015-11-24
相关资源
最近更新 更多