我正在开发一种小型设备,它具有相当大的配置参数(~100 KB),这些参数是从PC软件生成的。过去,我们将参数存储在二进制文件中,并将它们加载到数据结构中。维护有点烦人(不同的语言,确保结构中的字段顺序匹配,不同的版本等),所以我们正在考虑使用Google协议缓冲区。
从小型设备的角度来看,我担心存储序列化协议缓冲区所需的内存空间。我在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个字节。我知道这包括关键,可能是Variant编码的最坏情况,但我可以期待什么呢?较大的消息比较小的消息更有效,还是更依赖于编码值?
总之,我只是想了解一下协议缓冲区的内存空间使用情况。我讨厌使用易用性来大量增加存储配置数据所需的内存空间。谢谢!
答案 0 :(得分:2)
int32
被写为 varint ,这意味着对于正值,它所占用的空间取决于幅度。小正值可以是单字节;较大的正值可能需要更多。负值会占用更多空间 - 特别是,它需要与非常大的 64位数字相同。 “varint”是7位加上延续;所以负数(或大的正数)可以占用10个字节。为避免这种情况,如果您知道自己的值可能为负值,则可以使用sint32
/ sint64
- 这会使用 zig-zag 编码(然后 varint ) - 基本上使小幅度值比大幅度值占用更少的空间(无论符号如何)。
如果您需要针对最坏情况进行优化,那么可以考虑使用fixed32
/ fixed64
代替;这保证了恰好4或8个字节。
要点:
int32
/ int64
sint32
/ sint64
fixed32
/ fixed64
还有其他几个;完整的详细信息位于language guide
(在上面的所有情况下,你还需要包含标题,但通常是1或2个字节)
答案 1 :(得分:1)
Nanopb可以使用非常小的内存空间,它也可以直接与文件串行化,以避免需要内存缓冲区: http://koti.kapsi.fi/jpa/nanopb/