Производительным лица сериализация: БСЫНА против MessagePack (по сравнению с JSON)


недавно я нашел MessagePack альтернатива binary формат сериализации в Google Протокол Буферы и JSON который также превосходит оба.

и там BSON формат сериализации, который используется MongoDB для хранения данных.

может кто-нибудь разработать различия и dis - / преимущества BSON vs MessagePack?


просто чтобы завершить список исполняемых двоичных форматов сериализации: есть также Gobsкоторые будут преемником буферов протокола Google. Однако в отличие от всех других упомянутых форматов это не зависит от языка и полагаются на Go встроенное отражение есть также библиотеки Gobs, по крайней мере, на другом языке, чем Go.

3 116

3 ответа:

// обратите внимание, что я автор MessagePack. Этот ответ может быть предвзятым.

дизайн

  1. совместимость с JSON

    несмотря на свое название, совместимость BSON с JSON не так хороша по сравнению с MessagePack.

    BSON имеет специальные типы, такие как" ObjectId"," Min key"," UUID "или" MD5 " (я думаю, что эти типы требуются MongoDB). Эти типы не совместимы с JSON. Это означает какой-то тип информация теряется при преобразовании объектов из BSON в JSON. Это может быть недостатком для использования как JSON, так и BSON в одном сервисе.

    MessagePack предназначен для прозрачного преобразования из / в JSON.

  2. MessagePack меньше, чем BSON

    формат MessagePack менее подробный, чем BSON. В результате MessagePack может сериализовать объекты размером меньше BSON.

    например, простая карта {"a": 1,"b": 2} сериализуется в 7 байты с MessagePack, в то время как BSON использует 19 байт.

  3. BSON поддерживает обновление на месте

    С помощью BSON вы можете изменить часть сохраненного объекта без повторной сериализации всего объекта. Предположим, что карта {"a": 1,"b": 2} хранится в файле, и вы хотите обновить значение" a " от 1 до 2000.

    С MessagePack, 1 использует только 1 байт, но 2000 использует 3 байта. Таким образом, "b" должен быть перемещен назад на 2 байта, а "b" - нет модифицированный.

    С BSON, как 1, так и 2000 используют 5 байт. Из-за этой многословности вам не нужно перемещать "b".

  4. MessagePack имеет RPC

    MessagePack, буферы протокола, бережливость и Avro поддерживают RPC. Но БСОН этого не делает.

эти различия подразумевают, что MessagePack изначально предназначен для сетевой связи, в то время как BSON предназначен для хранения.

реализация и API дизайн

  1. MessagePack имеет API проверки типов (Java, C++ и D)

    MessagePack поддерживает статическую типизацию.

    динамическая типизация, используемая с JSON или BSON, полезна для динамических языков, таких как Ruby, Python или JavaScript. Но хлопотно для статических языков. Вы должны написать скучные коды проверки типа.

    MessagePack предоставляет API проверки типов. Он преобразует динамически типизированные объекты в статически типизированные объекты. Вот простой пример (на C++):

    #include <msgpack.hpp>
    
    class myclass {
    private:
        std::string str;
        std::vector<int> vec;
    public:
        // This macro enables this class to be serialized/deserialized
        MSGPACK_DEFINE(str, vec);
    };
    
    int main(void) {
        // serialize
        myclass m1 = ...;
    
        msgpack::sbuffer buffer;
        msgpack::pack(&buffer, m1);
    
        // deserialize
        msgpack::unpacked result;
        msgpack::unpack(&result, buffer.data(), buffer.size());
    
        // you get dynamically-typed object
        msgpack::object obj = result.get();
    
        // convert it to statically-typed object
        myclass m2 = obj.as<myclass>();
    }
    
  2. MessagePack имеет IDL

    это связано с API проверки типов, MessagePack поддерживает IDL. (спецификация доступна от:http://wiki.msgpack.org/display/MSGPACK/Design+of + IDL)

    буферы протокола и бережливость требуют IDL (не поддерживают динамическую типизацию) и обеспечивают более зрелую реализацию IDL.

  3. MessagePack имеет потоковый API (Ruby, Python, Java, C++, ...)

    MessagePack поддерживает потоковые десериализаторы. Эта функция полезна для сетевого взаимодействия. Вот пример (Ruby):

    require 'msgpack'
    
    # write objects to stdout
    $stdout.write [1,2,3].to_msgpack
    $stdout.write [1,2,3].to_msgpack
    
    # read objects from stdin using streaming deserializer
    unpacker = MessagePack::Unpacker.new($stdin)
    # use iterator
    unpacker.each {|obj|
      p obj
    }
    

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

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

некоторые среды могут есть очень быстрая сериализация и десериализация в/из msgpack/protobuf, другие не так много. В общем, чем ниже уровень языка/среды, тем лучше будет работать двоичная сериализация. В языках более высокого уровня (node.js, .Net, JVM) вы часто увидите, что сериализация JSON на самом деле быстрее. Тогда возникает вопрос, Является ли ваша сетевая нагрузка более или менее ограниченной, чем ваша память/процессор?

Что касается msgpack vs BSON vs protocol buffers... msgpack-это наименьшие байты группы, буферы протокола примерно одинаковы. BSON определяет более широкие собственные типы, чем два других, и может лучше соответствовать вашему объектному режиму, но это делает его более подробным. Буферы протокола имеют то преимущество,что они предназначены для потоковой передачи... что делает его более естественным форматом для двоичного формата передачи / хранения.

лично я бы склонялся к прозрачности, которую JSON предлагает напрямую, если нет явной необходимости в более легком трафике. Свыше HTTP с данными gzipped, разница в сетевых накладных расходах еще меньше проблемы между форматами.

быстрый тест показывает, что уменьшенный JSON десериализуется быстрее, чем двоичный MessagePack. В статье тесты.json-это 550kb minified JSON, статья.mpack-это MP-версия 420KB. Может быть вопрос реализации, конечно.

MessagePack:

//test_mp.js
var msg = require('msgpack');
var fs = require('fs');

var article = fs.readFileSync('Article.mpack');

for (var i = 0; i < 10000; i++) {
    msg.unpack(article);    
}

JSON:

// test_json.js
var msg = require('msgpack');
var fs = require('fs');

var article = fs.readFileSync('Article.json', 'utf-8');

for (var i = 0; i < 10000; i++) {
    JSON.parse(article);
}

так раз несколько:

Anarki:Downloads oleksii$ time node test_mp.js 

real    2m45.042s
user    2m44.662s
sys     0m2.034s

Anarki:Downloads oleksii$ time node test_json.js 

real    2m15.497s
user    2m15.458s
sys     0m0.824s

таким образом, пространство сохраняется, но быстрее? Нет.

проверены версии:

Anarki:Downloads oleksii$ node --version
v0.8.12
Anarki:Downloads oleksii$ npm list msgpack
/Users/oleksii
└── msgpack@0.1.7