最大序列化Protobuf消息大小

tra*_*veh 5 protocol-buffers

有没有办法在序列化后获得某个protobuf消息的最大大小?

我指的是不包含"重复"元素的消息.

请注意,我并不是指具有特定内容的protobuf消息的大小,而是指它可以达到的最大可能大小(在最坏的情况下).

Ken*_*rda 16

通常,任何protobuf消息都可以是任何长度,因为可能存在未知字段.如果您收到消息,则无法对长度做出任何假设.如果您要发送自己构建的消息,那么您可以假设它只包含您知道的字段 - 但是,在这种情况下,您还可以轻松计算确切的消息大小.因此,询问最大尺寸是多少通常没有用.

话虽如此,您可以编写使用Descriptor接口迭代FieldDescriptors消息类型(MyMessageType::descriptor())的代码.

请参阅:https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.descriptor

类似的接口存在于Java,Python和其他可能的接口中.

以下是要实施的规则:

每个字段由标记后跟一些数据组成.

对于标签:

  • 字段编号1-15具有1字节标记.
  • 字段编号16及以上具有2字节标记.

对于数据:

  • bool 总是一个字节.
  • int32,int64,uint64,和sint64具有10个字节(是的,最大数据长度int32可以是10个字节,如果它是负的,不幸的是).
  • sint32并且uint32最大数据长度为5个字节.
  • fixed32,sfixed32float,总是正好4个字节.
  • fixet64,sfixed64double,总是正好是8个字节.
  • 枚举字段的最大长度取决于最大枚举值:
    • 0-127:1个字节
    • 128-16384:2个字节
    • ...它是每字节7位,但希望你的枚举不是那么大!
    • 另请注意,负值将被编码为10个字节,但希望没有.
  • 消息类型字段的最大长度是消息类型的最大长度加上长度前缀的字节.长度前缀再次是每7位整数数据一个字节.
  • 组(您不应该使用它们;它们是在protobuf公开发布之前弃用的旧的功能)最大大小等于内容的最大大小加上第二个字​​段标记(参见上文).

如果您的邮件包含以下任何内容,则其最大长度不受限制:

  • 任何类型string或领域bytes.(除非你知道它们的最大长度,在这种情况下,它是最大长度加上长度前缀,就像子消息一样.)
  • 任何重复的字段.(除非你知道它的最大长度,在这种情况下,列表的每个元素都有一个最大长度,好像它是一个独立的字段,包括标记.这里没有总长度前缀.除非你使用[packed=true],在这种情况下你必须查看细节.)
  • 扩展.

  • @tigrou是的我确定,因为我写了代码.:)负int32必须填充到10个字节,因为int32s预期与int64s向前兼容,因此如果需要,可以在将来将现有的int32字段更改为int64. (5认同)

jpa*_*jpa 5

据我所知,谷歌自己的 protobuf 中没有计算最大大小的功能。

Nanopb 生成器在可能的情况下计算最大大小并将其导出为#define生成的文件中。

根据protobuf 编码文档,手动计算小消息也非常简单。