Кодирование, типы данных и упакованные повторяющиеся поля - PullRequest
1 голос
/ 06 февраля 2012

У меня есть несколько вопросов, касающихся упакованных полей и хранения / сериализации данные с протокольными буферами. По сути, я хочу сохранить в файл 4 МБ данных.

Данные, которые у меня есть (в нашей встроенной системе), принимаются как uint8_t (байт), и я хочу сохранить эти данные максимально эффективно.

Я тестировал множество прототипов (четыре);

repeated uint32_t datastruct = 1;
repeated uint32_t datastruct = 1 [packed = true]

с обоими вариантами, назначенными 1-к-1 (помещая uint8 в uint32), и оба варианта сдвинуты по битам с 4 значениями, помещенными в uint32_t.

К моему удивлению, сохраненные файлы намного больше оригинальных данные. (примеры, где я помещал uint8 в uint32, конечно ожидались ..) Лучший результат, который я смог достичь, был 5,2 МБ для данных 4 МБ, что на самом деле это не так хорошо.

Я неправильно понял что-то важное здесь? Я понимаю, что protobuf добавляет информацию в пакеты, но 25% увеличение слишком много imho.

Также использование GzipOutputStream увеличивает размер файла вместо его уменьшения.

Любые советы будут очень признательны!

Спасибо за ваше время.

Ответы [ 2 ]

2 голосов
/ 06 февраля 2012

Этот ответ основан на предположении, что вы используете uint32 в терминах .proto:

packed является положительным моментом (удаляет заголовки для значения);однако, упаковав один uint8 в uint32, вы сталкиваетесь с аспектом кодирования «varint», в частности, если установлен самый старший бит байта, он будет занимать 2 байта (varint использует 7 бит на байт дляданные и один бит как продолжение ).Следовательно, я бы порекомендовал переключиться на тип bytes, который представляет любой произвольный кусок байтов и кодируется «как есть», без какой-либо переменной или подобного.Это не будет повторяться / упаковываться - просто:

[required|optional] bytes data = 1;

Другой вариант - использовать fixed32 (повторяется и упаковывается) и помещать (с помощью сдвига) 4 байта на значение, но к тому времениВы сделали это и можете перейти к bytes и получить более очевидную карту 1: 1.

Re gzip;gzip нередко увеличивает размер произвольного двоичного файла без множества повторяющихся блоков.Напротив, если ваш документ protobuf содержит строки, размер обычно уменьшается, так как gzip может обнаружить повторяющиеся блоки.

1 голос
/ 06 февраля 2012

Если вы хотите сохранить последовательность байтов, используйте тип данных bytes. Накладные расходы будут крошечными.

Дополнительные издержки, которые вы видите от int32, связаны с кодированием переменной длины; числа хранятся с 7 битами в каждом байте, а 8-й указывает, есть ли еще Таким образом, для полноразмерного 32-битного значения потребуется 5 байтов для хранения. Существует тип fixed32, который всегда принимает 32 бита (4 байта) на значение - это будет более эффективным, если большинству значений требуется 32 бита для представления, и менее эффективно, если большинство значений будет маленьким.

...