一个Google protocol buffer通常占用多少内存空间?

3

我正在开发一个小型设备,它有一组相当大的配置参数(约100KB),这些参数是由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编码的最坏情况,但是前进时我可以期望什么? 更大的消息比较小的消息更有效,还是更依赖于编码值?
总之,我只是想了解协议缓冲区中的内存空间使用情况。 我不想为了存储配置数据而牺牲易用性以换取大量增加的内存空间。 谢谢!
2个回答

3

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

如果您需要优化最坏情况,那么也许考虑使用fixed32/fixed64代替;这保证只占用4或8个字节。

总结:

  • 始终(或几乎始终)为正数,并且通常为小到中等大小:int32/int64
  • 正数或负数,并且通常为小到中等幅度:sint32/sint64
  • 大值,或需要保证大小:fixed32/fixed64

还有一些其他的;完整详情请参见语言指南

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


1
Nanopb 可以在非常小的内存空间中工作,并且它还可以直接序列化到/从文件中,避免了对内存缓冲区的需求: http://koti.kapsi.fi/jpa/nanopb/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接