【问题标题】:proto3 - oneof vs fields with identifierproto3 - oneof vs 带有标识符的字段
【发布时间】:2020-07-01 21:57:39
【问题描述】:

我正在为一个对象编写一个 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...
}

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

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

【问题讨论】:

    标签: protocol-buffers proto proto3


    【解决方案1】:

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

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

    【讨论】:

    • 这是一个 java 应用程序,我正在使用 Google 的 protobuf-java 库
    • 不幸的是,我对 java 实现一无所知。也许您可以查看代码或专门询问嵌套消息与 oneof 的分配方式。
    • OP 我也在用Java,你有没有设法查看内存使用情况?
    猜你喜欢
    • 1970-01-01
    • 2020-07-07
    • 2021-07-05
    • 1970-01-01
    • 1970-01-01
    • 2020-10-06
    • 2012-03-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多