在 protobuf 消息或嵌套消息中最好有很多字段吗?

Is it best to have many field in protobuf message or nested messages?

我试图在网上找到一些建议,但找不到任何相关内容。

假设我正在创建一个包含很多字段 (50+) 的协议缓冲区消息。最好将所有字段保持在同一级别还是将它们组织在子消息中?对性能有任何影响吗?

示例:

message myMessage{
 string field1 = 1;
 string field2 = 2;
 ....
 string fieldn = n;
}

message myMessage{
 SubMessage1 groupedfieldsbasedonsomebusinesslogic1 = 1;
 SubMessage2 groupedfieldsbasedonsomebusinesslogic2 = 2;

 message SubMessage1{
  string field1 = 1;
  string field2 = 2;
  ... 
  string fieldx = x;
 } 

 message SubMessage2{
  string fieldxplus1 = x+1;
  ... 
  string fieldn = n;
 }
}

我在这里没有过多考虑可读性,因为在反序列化为平面数据或嵌套数据时有利有弊。我的问题实际上是关注技术影响。

没有"best" - 一切都是上下文相关的,只有你拥有大部分上下文。

但是!关于性能的一些小想法:

  • 嵌套方法需要更多 object;通常这很好,除非你的体积很大
  • 嵌套方法可能更容易理解 object 模型和数据某些部分之间的关​​系
  • 平面方法需要更大的字段数;字段编号 1-15 占用一个字节 header;字段编号 16-2047 需要 2 个字节 header(依此类推);实际上,几个字段的这个额外字节不太可能对您造成太大伤害,并且被替代(嵌套)方法的开销所抵消:
  • 嵌套方法需要每个 sub-object 一个 length-prefix 或一个 start/end 令牌(协议中的 "group");就额外尺寸而言,这并不多,但是:
    • length-prefixe 要求序列化程序提前知道长度,这意味着 double-processing("compute length" 扫描),或者缓冲;在大多数情况下,这不是一个大问题,但对于非常大的 sub-graphs
    • 来说可能会有问题
    • start/end 令牌是 google 一直试图杀死的东西,并且在所有库中都没有得到很好的支持(并且 IIRC 它在 "proto3" 模式中不存在);不过,我仍然很喜欢它,在某些情况下 :) protobuf-net(来自标签)支持将任意 sub-data 编码为组的能力,但如果你需要 x-plat 可能会很尴尬后来

在所有这些事情中,如果是我,我会关注的是第二个

也许从一些看起来可用的东西开始,然后测量它的实际数据量;它的表现是否令人满意?