Как буфер протокола Google сравнивается с ASN.1 - PullRequest
28 голосов
/ 27 февраля 2009

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

Ответы [ 3 ]

21 голосов
/ 14 декабря 2010

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

8 голосов
/ 27 февраля 2009

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

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

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

4 голосов
/ 23 октября 2014

Когда важен размер упакованного / закодированного сообщения, вы должны также отметить тот факт, что 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 байтами (значения в диапазоне макс.) И 500 байтами (все значения являются старшими 32-битными значениями).

...