c++ - 编码、数据类型和打包的重复字段

标签 c++ serialization protocol-buffers

我有一些关于打包字段和存储/序列化的问题 带有 Protocol Buffer 的数据。 我基本上想做的是将 4MB 的数据存储到一个文件中。

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

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

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

两个变体都被一对一分配(将 uint8 赋值给 uint32),并且两个变体都用 4 个值移位到一个 uint32_t 中。

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

我是不是误解了一些重要的东西? 我确实意识到 protobuf 向数据包添加了信息,但是 25% 恕我直言,增加太多了。

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

如有任何提示,我们将不胜感激!

感谢您的宝贵时间。

最佳答案

这个答案是基于你在 .proto 术语中使用 uint32 的假设:

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

[required|optional] bytes data = 1;

另一种选择是使用 fixed32(重复和压缩),并为每个值放置(通过移位)4 个字节,但是当您完成后,您也可以转到 bytes 有更明显的1:1映射。

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

关于c++ - 编码、数据类型和打包的重复字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9160646/

相关文章:

javascript - 序列化列表的好方法? - Javascript/AJAX

serialization - 使用 xmlSerializer.Serialize 和 IEnumerable 对象序列化对象

c++ - 如何在C++的protobuf中从 `GzipInputStream`读取特定大小的消息?

rust - 如何确定由 include! 包含的 rust-protobuf 生成的 .rs 文件中的消息宏观

c++ - undefined symbol 'fixed_address_empty_string' : new tensorflow op with protobuf

C++11 非拥有引用/指向 unique_ptr 的指针?

c++ - reinterpret_cast 是否保证不更改源指针的地址?

c++ - 跳转到 VLA 阵列上时出现段错误

c++ - 数组搜索和唯一增值

c# - ServiceStack.Text 没有按预期序列化我的对象