proto3 - 一个与标识符的字段

proto3 - oneof vs fields with identifier

我正在为一个对象编写 proto3 class,该对象目前有大约 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...
}

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

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

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

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

分配内存