Как буферы протокола Google сравниваются с ASN.1
-
09-09-2019 - |
Вопрос
Каковы наиболее заметные различия между буферами протокола Google и ASN.1 (для КАЖДОЙ кодировки)?Для моего проекта наиболее важной проблемой является размер сериализованных данных.Кто-нибудь проводил какие-либо сравнения размеров данных между этими двумя?
Решение
Прошло много времени с тех пор, как я выполнял какую-либо работу ASN.1, но размер, скорее всего, будет зависеть от деталей ваших типов и фактических данных.
Я бы так и сделал сильно рекомендую вам создать прототип обоих и ввести некоторые реальные данные для сравнения.
Если ваш буфер протокола будет содержать повторяющиеся примитивные типы, вам следует обратиться к последнему источнику в Subversion для поиска буферов протокола - теперь они могут быть представлены в "упакованном" формате, который намного экономит место.(Мой порт C # имеет просто познакомился с этой функцией где-то на прошлой неделе.)
Другие советы
Если вы используете ASN.1 с невыровненным значением PER и определяете свои типы данных, используя соответствующие ограничения (например, указывая нижние / верхние границы для целых чисел, верхние границы для длины списков и т.д.), ваши кодировки будут очень компактными.Никакие биты не будут потрачены впустую на такие вещи, как выравнивание или заполнение между полями, и каждое поле будет закодировано в минимальном количестве битов, необходимом для хранения его допустимого диапазона значений.Например, поле типа INTEGER (1..8) будет закодировано в 3 бита (1='000', 2='001', ..., 8='111');и ВЫБОР с четырьмя альтернативами будет занимать 2 бита (указывающий на выбранную альтернативу) плюс биты, занятые выбранной альтернативой.ASN.1 обладает многими другими интересными функциями, которые были успешно использованы во многих опубликованных стандартах.Примером является маркер расширения ("..."), который при применении к ПОСЛЕДОВАТЕЛЬНОСТИ, ВЫБОРУ, ПЕРЕЧИСЛЯЕМОМУ и другим типам обеспечивает обратную и прямую совместимость между конечными точками, реализующими различные версии спецификации.
Когда важен размер упакованного / закодированного сообщения, вы также должны отметить тот факт, что 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, то в результате размер упакованного сообщения с protobuf составит примерно от 250 до 450 байт, в зависимости от того, какие значения на самом деле содержит массив.Это может даже увеличиться до более чем 1000 байт, если вы используете полный 32-битный диапазон или в случае, если вы используете int32
вместо того , чтобы sint32
и имеют отрицательные значения.
Большой двоичный объект необработанных данных (при условии, что z может быть определен как int16
значение) потребляло бы всего 320 байт и, таким образом, АСН.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-битные значения).