proto3 - одно из полей с идентификатором - PullRequest
0 голосов
/ 20 марта 2020

Я пишу класс 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, которое ссылается на указанный c подтип.

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...
}

Меня особенно интересует размер провода и производительность.

Во втором варианте, учитывая, что будет установлен только один из вариантов (применяется на уровне приложения), будет ли размер провода больше, чем в первом? Память также зарезервирована для пустых полей?

1 Ответ

1 голос
/ 24 марта 2020

Метод oneof немного лучше по сравнению с сообщением, в котором вы определяете переменную type относительно мощности обработки и размера провода. Protobuf всегда сериализует номер тега перед вложенным сообщением. Поэтому для сообщения oneof необязательно сериализовать переменную типа type. Уменьшить размер провода по сравнению со вторым определением сообщения.

Что касается распределения памяти, это сильно зависит от языка программирования, который вы используете, и от того, как они реализовали одно или вложенные сообщения. Если я не ошибаюсь, реализация C ++ по умолчанию динамически распределяет память для вложенных сообщений. Я подозреваю, что нет никакой разницы между любым из ваших предложений. Глядя на NanoPB , однако, один из них реализован в виде союзов, выделяющих только память для большего сообщения. В то время как для вашего второго варианта будет выделена память для B1 и B2.

...