Micro Property — минималистичный сериализатор двоичных данных для embedded систем. Часть 2

Некоторое время назад я опубликовал свою статью о разработке велосипедного велосипеда, в которой описал причины, побудившие меня этим заняться.

Если вкратце, то мне была нужна миниатюрная библиотека для микроконтроллеров с сериализатором двоичных данных для последующей передачи этих сообщений по низко скоростным линиям связи, тогда как обычные форматы xml, json, bson, yaml, protobuf, Thrift, ASN.1 и др. мне по разным причинам не подходили.

Как и ожидалось, решение оказалось более чем велосипедом, и тем не менее, сама публикация статьи на Хабре мне очень сильно помогла. Дело в том, что при первоначальном анализе возможных библиотек, я почему то упустил из вида сериализаторы MessagePack CBOR, UBJSON.

Ссылки на них мне написали в комменатриях уже после публикации статьи. И я сразу понял, что скорее всего CBOR, UBJSON легко решают стоящую передо мной задачу. Причем делают этого гораздо лучше, чем моя собственная разработка, про что я честно написал в начале статьи.

После этого я прикрутил к библиотеке CBOR свой интерфейс (чтобы не перелопачивать исходники), и … решил от этого формата отказаться в пользу MessagePack 🙂

CBOR vs. MessagePack

На самом деле CBOR и MessagePack форматы используют один и тот же принцип сериализации данных. В их основе лежит практичный метод записи TLV, за тем лишь исключением, что в классическом виде TLV всегда содержит поля значения тега и размера значения. А вот последнее поле может отсутствовать, если его размер ноль.

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

В исходной статье я писал про то, что мне требуется максимальная упаковка бинарных данных и оба эти два формата справляются с такой задачей на ура. Они между собой очень похожи, и отличаются только количеством бит, в котором сохранится значения типа поля.

В формате CBOR минимальные накладные расходы на хранение каждого поля три бита. т.е. в первом байте каждого поля первые три бита отвечают за тип содержимого, и в зависимости от него интерпретируют наличие и размер других полей, а оставшиеся 5 бит могут содержать уже само значение поля (0 до 31).

А вот в MessagePack пошли еще дальше! В этом формате минимальные накладные расходы на хранение значения составляют всего 1 (ОДИН!) бит информации. Соответственно и диапазон возможных значений для хранения с помощью одного байта значительно больше (0 до 127). А для указания дополнительной информации о типе поля используются значения с установленным старшим битом.

Понятно, что диапазон представления отрицательных значений в первом байте при таком способе кодирования уменьшается за счет положительных чисел (в одном байте можно хранить только 32 отрицательны числа, а для остальных значений уже потребуется второй байт). Но это правильный дисбаланс и смещен он в нужную сторону, т.к. на практике положительные числа используются значительно чаще отрицательных.

Именно этот момент, а так же нормальная библиотека с реализацией формата на десятке разных языков и определили мой окончательный выбор в пользу формата MessagePack. Думаю, что я не единственный, кому могут быть интересны такие подробности, поэтому я посчитал правильным ими поделиться.

В результате, изначальный формат сериализатора удалось сделать еще компактнее, в том числе и за счет некоторых соглашений (например, структуру кодируемых данных ограничить только плоским списком и отказом от использования невостребованных типов), а мой сон стал спокойнее, т.к. уже не болит голова насчет совместимости на уровне форматов пересылаемых сообщений между устройствами.

Большое спасибо Хабра-юзерам Spym и edo1h, что ответили предыдущую публикацию и тем самым помогли найти решение действительно серьезной проблемы такими малыми усилиями!

Первоисточники:

Спецификация CBOR. Есть хорошая статья с описанием на Хабре.

Спецификация MessagePack очень легко читается в документации и не требует какого либо перевода или дополнительных пояснений.

Let’s block ads! (Why?)

Read More

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *