Потерянные байты в буферных массивах протокола? - PullRequest
3 голосов
/ 06 марта 2011

У меня есть настройка буфера протокола:

[ProtoContract]
Foo
{
    [ProtoMember(1)]
    Bar[] Bars;
}

Одна строка кодируется в 67-байтовый буфер протокола.Это звучит правдоподобно, потому что я знаю, что Bar - это всего лишь 64-байтовый массив, а затем есть 3 байта для префикса длины.занимает 1362 байта.20 * 67 - это 1340, поэтому для кодирования массива используются 22 байта!

Почему это занимает так много места?И могу ли я что-нибудь сделать, чтобы уменьшить его?

Ответы [ 2 ]

5 голосов
/ 07 марта 2011

Эти служебные данные - это просто информация, которая должна знать, где начинается и заканчивается каждый из 20 объектов.Здесь нет ничего, что я могу сделать по-другому, не нарушая формат (то есть делая что-то, противоречащее спецификации).

Если вы действительно хотите узнать подробности:

Массив или список (если мыисключить «упакованный», что здесь не применимо) просто повторяющийся блок вложенных сообщений.Для вложенных сообщений доступны две раскладки;строки и группы.Со строкой макет выглядит следующим образом:

[header][length][data]

, где header - закодированное с помощью варинтов сусло типа провода и номера поля (в данном случае это шестнадцатеричное 08 с полем 1), lengthэто размер в кодировке varint data, а data это сам подобъект.Для небольших объектов (data менее 128 байт) это часто означает 2-байтовые издержки на объект в зависимости от: номера поля (поля выше 15 занимают больше места) и b: размера данных.

Для группы макет имеет вид:

[header][data][footer]

, где header - это закодированное с помощью varint сусло типа провода и номера поля (в данном случае это шестнадцатеричный 0B с полем 1), data - это подобъект, а footer - это еще одна переменная, которая указывает на конец объекта (в данном случае это шестнадцатеричный код 0C с полем 1).

Обычно группы менее предпочтительны, но имеютпреимущество в том, что они не несут накладных расходов, так как data увеличивается в размере.Для небольших номеров полей (менее 16) опять-таки служебные данные составляют 2 байта на объект.Конечно, вы платите вдвое больше за большие номера полей.

2 голосов
/ 06 марта 2011

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

Так что я предполагаю, что на самом деле у вас есть 1 байт для каждого повторного элемента массиваплюс 2 дополнительных байта сверху.

Вы можете потерять накладные расходы, используя «упакованный» массив.Protobuf-net поддерживает это: http://code.google.com/p/protobuf-net/

Документация для двоичного формата находится здесь: http://code.google.com/apis/protocolbuffers/docs/encoding.html

...