habrahabr

MessagePack аналог JSON, но быстрее и меньше

  • понедельник, 23 февраля 2015 г. в 02:12:29
http://habrahabr.ru/post/251177/

MessagePack это эффективный сериализатор данных в бинарное представление.



Используя данную библиотеку вы можете обмениваться сообщениями между вашими компонентами системы подобно тому, как вы это делаете с помощью формата JSON. Интерпретация библиотеки существует для 44 языков программирования (!)

Несколько простых наглядных примеров на PHP:

php -r 'echo strlen(json_encode(array("Hello World!")));' // 16
php -r 'echo strlen(msgpack_pack(array("Hello World!")));' // 14

php -r 'echo strlen(msgpack_pack(array("Hello World!", "Hello World!")));' // 27
php -r 'echo strlen(json_encode(array("Hello World!", "Hellow World!")));' // 32

php -r 'echo strlen(json_encode(array("Hello World!" => "Hello World!")));' // 31
php -r 'echo strlen(msgpack_pack(array("Hello World!" => "Hello World!")));' // 27

На данных синтетических примерах видно, что MessagePack упаковывает данные на 15-20% эффективнее чем JSON. В нагруженном проекте обмен сообщениями между компонентами системы насчитывает 100 тысяч в день и более. Экономя 15-20% трафика вы сможете обслуживать больше сообщений на одной ноде за тот же период времени.

Библиотека полностью совместима с JSON, но все же стоит знать некоторые ограничения:
  • Значение Integer ограничено от -(2^63) до (2^64)-1;
  • Значение Float представлено стандартом IEEE 754 с одинарной или двойной точностью;
  • Максимальная длина бинарного объекта (2^32)-1;
  • Максимальный размер байт строки (2^32)-1;
  • Строка может содержать недопустимую последовательность байтов. В этой ситуации поведение десериализатора зависит от фактической реализации, когда он получит недопустимую последовательность байтов.

    Из этого следует, что в каждом из языков будет свое поведение. Например, в случае, если вы распаковываете данные на PHP будет автоматически сгенерировано:
    Warning: [msgpack] (php_msgpack_unserialize) %s %d в ваш STDERR

    Но его можно отключить используя php.ini через флаг msgpack.error_display=0 (по умолчанию 1);
  • Максимальное количество элементов в массиве может быть не больше чем (2^32)-1;
  • Максимальное количество элементов в ассоциативном массиве (ключ=>значение) может быть не больше чем (2^32)-1;

Подробно со спецификацией упаковки данных вы можете ознакомится по адресу github.com/msgpack/msgpack/blob/master/spec.md

Установка и настройка библиотеки весьма тривиальна и разработчики заботятся о том, чтобы не создавать трудности на этом этапе. Так в случае использования PHP все сводится к знакомой конструкции:

pecl install msgpack
Пример, для Python:
pip install u-msgpack-python //либо easy_install u-msgpack-python
Для Ruby:
gem install msgpack

Возраст библиотеки уже более 3 лет.

Последняя актуальная версии расширения для PHP на текущий момент — 0.5.5.
В ней было замечено, что кроме стандартных функций msgpack_pack и msgpack_unpack (которые являются алиасами к msgpack_serialize и msgpack_unserialize) есть ещё два undocument класса MessagePack и MessagePackUnpacker. Они имеют следующие интерфейсы:

MessagePack
MessagePack::__construct(boolean $opt = null); // $opt - управление поведением флага php.ini msgpack.php_only внутри класса 
MessagePack::setOption(integer $option, boolean $value); // поддерживает только опцию MSGPACK_CLASS_OPT_PHPONLY
MessagePack::pack(mixed $value); // упаковывает данные и возвращает строку
MessagePack::unpack(string $str, $object = null); // распаковывает строку. Вторым параметром можно передать строку, объект, массив, который следует заполнить распакованными данными и вернуть в результате выполнения функции.
MessagePack::unpacker(); // возвращает объект класса MessagePackUnpacker. Обратите внимание, что в текущей реализации библиотеки при каждом обращении создается новый экземпляр класса.

MessagePackUnpacker
MessagePackUnpacker::__construct(boolean $opt = null); // $opt - управление поведением флага php.ini msgpack.php_only внутри класса 
MessagePackUnpacker::__destruct();
MessagePackUnpacker::setOption(integer $option, boolean $value); // поддерживает только опцию MSGPACK_CLASS_OPT_PHPONLY
MessagePackUnpacker::feed(string $str); // Добавляет указанную строку к общему буферу. Возвращает true либо false.
MessagePackUnpacker::execute(string $str = null, integer &$offset = null); // Распаковывает данные. Возвращает true либо false.
MessagePackUnpacker::data(mixed $object = null); // В случае, если данные не были распакованы через метод execute возвращает false. В случае, если данные были распакованы и не был передан параметр $object - возвращает распакованную строку и вызывает метод reset. В случае, если данные были распакованы и был передан параметр $object работает по принципу MessagePack::unpack и вызывает метод reset.
MessagePackUnpacker::reset(); // очищает текущий буфер;

Официальный сайт разработчиков msgpack.org/
P.S.: к разработчикам библиотеки не отношусь. Использую её в работе 4 месяца.