0

我正在为一个对象编写一个 proto3 类,该对象目前有大约 2 个变体,并且将增长到 6 或 7 个。其中只有一个会在消息中使用。这些变体不共享公共字段。它们将被编码为父消息中的子消息。这些消息将被写入一次并读取数万次。

我想知道什么是最高效的方式,内存和解析明智的时间,以实现这一点,以便随着更多变化的添加,性能不会丢失。

考虑以下变化。

message B1 {
    repeated string value = 1;
    bool hasMeta = 2;
}

message B2 {
    repeated int32 value = 1;
    map<string, string> foo = 2;
}

第一个选项:定义一​​个oneof引用特定子类型的字段。

message P1 {
    oneof parents {
        B1 boo = 1;
        B2 baz = 2;
        // add more variations here in future..
    }
    // other non-related fields...
}

第二个选项:定义一​​个整数作为可用变体的标识符。在运行时,此整数可用于确定已设置哪个变体(另一种方法是对变体进行空值检查并使用第一个非空值)。

message P1 {
    int32 type = 1;
    B1 boo = 2;
    B2 baz = 3;
    // other non-related fields...
}

我对电线尺寸和性能特别感兴趣。

在第二个选项中,考虑到只设置一个变体(在应用程序层中强制执行),电线尺寸会比第一个更大吗?是否也为空字段保留内存?

4

1 回答 1

1

type与在处理能力和线路尺寸方面定义变量的消息相比,oneof 方法稍好一些。Protobuf 总是在嵌套消息之前序列化标签号。因此,对于 oneof 消息,不需要序列化像type. 与第二个消息定义相比,使其线路尺寸略小。

关于内存分配,这在很大程度上取决于您使用的编程语言以及它们如何实现 oneof 和嵌套消息。如果我没记错的话,默认的 C++ 实现会为子消息动态分配内存。我怀疑您的任何一个建议都没有区别。然而,看看NanoPB,其中一个被实现为联合,只为更大的消息分配内存。而对于您的第二个选项,这将为B1和分配内存B2

于 2020-03-24T11:56:26.470 回答