【问题标题】:Is there alternative to flatbuffers struct in protobuf?protobuf 中是否有替代 flatbuffers 结构的方法?
【发布时间】:2021-08-22 15:20:40
【问题描述】:

问题是关于 protobuf,但首先我想从 flatbuffers 中解释类似的概念:

我知道在 flatbuffers 中我可以创建具有如下标量类型的 Point2d 结构:

struct Point2d {
  x: double;
  y: double;
}

table PointCloud {
  point_array: [Point2d] (required);
}

这里的 struct 牺牲了模式演变,我可以忍受这一点,但作为回报,我可以拥有具有数百万个元素的此类点数组,开销几乎为 0,每个点结构(16 字节长)将是一个接一个地写入缓冲区,所以 2 个点需要 32 个字节,4 个点需要 64 个字节,等等。

我是 protobuf 世界的新手,但似乎 protobuf 总是 将带有字段 ID 的 varint 写入输出流,即使“消息”重复并包含标量类型也是如此。因此,对于每个重复的 point2d(16 个字节),我们有 2 个额外的 varint 字节,它们在“数组”中完全没用。

我说的对吗?它是否会在 point_array 中每个重复点的每个 x 和 y 字段之前实际写入 varint 字节? protobuf 中是否有替代 flatbuffer struct 的方法?

更具体地说,我包含类似于 flatbuffer 文件的 proto:

message Point2d {
  double x = 1;
  double y = 2;
}

message PointCloud {
  // Is protobuf serializing 2 varints with each Point2d in this repeated field?
  repeated Point2d point_array = 1;
}

【问题讨论】:

  • 另外两个 varint 并不是没用的。您将如何支持升级到 3d 矢量(x、y、z)?你怎么知道 3 point2d 的数组和 2 point3d 的数组之间的区别?具有小值的 varint 使用单个字节进行序列化。与您为兼容性方案支付的价格相比,开销很小。没有什么能阻止您使用双精度数组和一个指示点大小的单个 int 发出消息
  • 1 - 我永远不需要将 2d 点升级到 3d 点。 2 - point_array 有 field-id,并且这个 id 已经与类型相关联(它是 2d 点的数组)。

标签: protocol-buffers flatbuffers


【解决方案1】:

在protobuf中,你不能避免结构化数据中的字段头,但是:如果你使用一个非结构化的简单数组,它可以被“打包”(这只是意味着:没有字段头)。当使用诸如 int32 之类的“重复”原语时,这在 proto3 中是自动的。在 proto2 中,您需要选择使用打包标记。

【讨论】:

  • 请注意,当使用打包的重复字段时,数组中的元素数量将被序列化。你会得到:|编号 |尺寸 | x, y |。使用非压缩重复字段时,您将获得:| id_x | x | id_y |是|。对于小的字段 id 数和元素数,这两个数组之间的实际序列化字节数不会变化,只有两个元素。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-06
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多