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

Ant*_*vre 6 database-design data-modeling protocol-buffers protobuf-net

我试图在网上找到一些建议,但找不到任何相关的建议.

假设我正在创建一个包含很多字段(50+)的协议缓冲区消息.最好是将所有字段保持在同一级别还是将它们组织在子消息中?这种或那种方式对表演有什么影响吗?

例:

message myMessage{
 string field1 = 1;
 string field2 = 2;
 ....
 string fieldn = n;
}
Run Code Online (Sandbox Code Playgroud)

VS

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;
 }
}
Run Code Online (Sandbox Code Playgroud)

我在这里并没有考虑可读性,因为在反序列化以获得平坦数据或嵌套数据时存在利弊.我的问题是真正关注技术影响.

Mar*_*ell 8

没有"最好的" - 一切都是上下文的,只有你拥有大部分的上下文.

然而!关于表现的一些小想法:

  • 嵌套方法需要更多对象; 通常这很好,除非你的数量庞大
  • 嵌套方法可以更容易理解对象模型以及数据的某些部分之间的关​​系
  • 平坦的方法需要更大的场数; 字段编号1-15采用单字节头; 字段编号16-2047需要2个字节的标题(依此类推); 实际上,这几个字段的额外字节不太可能对您造成太大影响,并且会被替代(嵌套)方法的开销所抵消:
  • 嵌套方法需要每个子对象的长度前缀,或者一个开始/结束标记(协议中的"组"); 这在额外的尺寸方面并不多,但是:
    • length-prefixe要求序列化器提前知道长度,这意味着要么进行双重处理("计算长度"扫描),要么进行缓冲; 在大多数情况下,这不是一个大问题,但对于非常大的子图可能会有问题
    • 开始/结束令牌是谷歌一直试图杀死的东西,并没有在所有库中得到很好的支持(而且IIRC在"proto3"模式中不存在); 我仍然非常喜欢它,但在某些情况下:) protobuf-net(来自标签)支持将任意子数据编码为组的能力,但如果你以后需要x-plat它可能会很尴尬

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

也许从看起来可用的东西开始,并测量它以获得真实的数据量; 它的表现是否可以接受?