2

我正在开发一个小型设备,它有一组相当大的配置参数(~100 KB),这些参数是从 PC 软件生成的。过去,我们将参数存储在二进制文件中并将它们加载到数据结构中。维护有点烦(不同的语言,确保结构中的字段顺序匹配,不同的版本等),所以我们正在考虑去谷歌协议缓冲区。

从小型设备的角度来看,我担心存储序列化协议缓冲区所需的内存空间。我在 C 中工作,所以我下载了protobuf-embedded-c并开始研究一个示例。我对它计算的缓冲区的最大大小感到有点惊讶。例如,下面是空缓冲区的大小,然后是包含命名类型的单个变量的缓冲区:

#define MAX_M_Empty_SIZE 2
#define MAX_M_double_SIZE 12
#define MAX_M_float_SIZE 8
#define MAX_M_int32_SIZE 14
#define MAX_M_int64_SIZE 14
#define MAX_M_uint32_SIZE 9
#define MAX_M_uint64_SIZE 14
#define MAX_M_sint32_SIZE 9
#define MAX_M_sint64_SIZE 14
#define MAX_M_fixed32_SIZE 8
#define MAX_M_fixed64_SIZE 12
#define MAX_M_sfixed32_SIZE 8
#define MAX_M_sfixed64_SIZE 12
#define MAX_M_bool_SIZE 5

每次我在结构中添加一个“int32”时,最大大小增加了 14 个字节。我知道这包括变体编码的关键和可能最坏的情况,但是我能期待什么?较大的消息比较小的消息更有效,还是更依赖于编码值?

总之,我只是想了解协议缓冲区上的内存空间使用情况。我讨厌用易用性换取大量增加存储配置数据所需的内存空间。谢谢!

4

2 回答 2

2

int32写为varint,这意味着对于正值,它占用的空间取决于大小。小的正值可以是单字节的;较大的正值可能需要更多。负值占用更多空间 - 特别是,它占用的空间与非常大的64 位数字相同。"varint" 是 7 位加续;所以一个负数(或一个大的正数)可以占用 10 个字节。为避免这种情况,如果您知道您的值可能是负数,您可以使用sint32/ sint64- 这使用zig-zag编码(然后是 varint) - 这基本上使小幅度值比大幅度值占用更少的空间(无论符号如何)。

如果您需要针对最坏情况进行优化,那么可以考虑使用fixed32/fixed64代替;这保证恰好占用 4 或 8 个字节。

概括:

  • 总是(或几乎总是)积极的,通常是小到中等大小:int32/int64
  • 正或负,通常为中小幅度:sint32/sint64
  • 较大的值,或者需要保证大小:fixed32/fixed64

还有一些其他的;完整的详细信息在语言指南中

(在上述所有情况下,您还需要包含标头,但这通常是 1 或 2 个字节)

于 2012-11-13T20:04:37.003 回答
1

Nanopb 可以使用非常小的内存空间,它还可以直接序列化到文件/从文件序列化以避免需要内存缓冲区: http: //koti.kapsi.fi/jpa/nanopb/

于 2012-11-14T06:59:36.147 回答