Подтвердить что ты не робот

Как сопоставить буферы протокола Google с ASN.1

Каковы наиболее заметные различия между буферами протокола Google и ASN.1 (с PER-кодированием)? Для моего проекта наиболее важной проблемой является размер сериализованных данных. Кто-нибудь сделал какие-либо сравнения размеров данных между этими двумя?

4b9b3361

Ответ 1

Я долгое время занимался какой-либо работой ASN.1, но размер, скорее всего, будет зависеть от деталей ваших типов и фактических данных.

Я бы настоятельно рекомендовал вам прототипировать оба и поместить некоторые реальные данные для сравнения.

Если ваш буфер протокола будет содержать повторяющиеся примитивные типы, вы должны посмотреть на последний источник в Subversion for Protocol Buffers - они могут быть представлены в "упакованном" формате, который теперь намного эффективнее. (Мой порт С# только что догнал эту функцию, некоторое время на прошлой неделе.)

Ответ 2

Если вы используете ASN.1 с Unaligned PER и определяете свои типы данных с использованием соответствующих ограничений (например, указывая нижние/верхние границы для целых чисел, верхние границы для длины списков и т.д.), ваши кодировки будут очень компактный. Не будет битов впустую для таких вещей, как выравнивание или заполнение между полями, и каждое поле будет закодировано в минимальном количестве бит, необходимых для хранения разрешенного диапазона значений. Например, поле типа INTEGER (1..8) будет закодировано в 3 бита (1 = '000', 2 = '001',..., 8 = '111'); и ВЫБОР с четырьмя альтернативами будет занимать 2 бита (с указанием выбранной альтернативы) плюс бит, занятый выбранной альтернативой. ASN.1 имеет много других интересных функций, которые были успешно использованы во многих опубликованных стандартах. Примером может служить маркер расширения ( "..." ), который при применении к SEQUENCE, CHOICE, ENUMERATED и другим типам обеспечивает обратную и прямую совместимость между конечными точками, реализующими разные версии спецификации.

Ответ 3

Когда размер упакованного/закодированного сообщения важен, вы также должны отметить тот факт, что protobuf не может упаковать поля repeated, которые не относятся к primitive numeric type, прочитайте это для получения дополнительной информации.

Это проблема, например. если у вас есть сообщения этого типа: (комментарий определяет действительный диапазон значений)

message P{
    required sint32 x = 1; // -0x1ffff  to  0x20000
    required sint32 y = 2; // -0x1ffff  to  0x20000
    required sint32 z = 3; // -0x319c  to   0x3200
}
message Array{
    repeated P ps = 1;
    optional uint32 somemoredata = 2;
}

Если длина массива равна, например, 32, то вы получите размер упакованного сообщения приблизительно 250-450 байт с protobuf, в зависимости от того, какие значения фактически содержит массив. Это может даже увеличиться до более чем 1000 байтов, если вы используете полный 32-битный диапазон или, если вы используете int32 вместо sint32 и имеете отрицательные значения.

Необработанный блок данных (предполагая, что z может быть определен как значение int16), будет потреблять только 320 байт, поэтому сообщение ASN.1 всегда меньше, чем 320 байт, так как максимальные значения на самом деле не 32 бит, а 19 бит (x, y) и 15 бит (z).

Размер сообщения protobuf можно оптимизировать с помощью этого определения сообщения:

message Ps{
    repeated sint32 xs = 1 [packed=true];
    repeated sint32 ys = 2 [packed=true];
    repeated sint32 zs = 3 [packed=true];
}
message Array{
    required Ps ps = 1;
    optional uint32 somemoredata = 2;
}

что приводит к размерам сообщений приблизительно от 100 байт (все значения равны нулю), 300 байт (значения в диапазоне max) и 500 байт (все значения имеют высокие 32-битные значения).