149

最近、私はMessagePackを見つけました。これは、Google のProtocol BuffersJSONの代替バイナリシリアル化形式であり、どちらも優れています。

また、データを格納するために MongoDB で使用されるBSONシリアル化形式もあります。

誰かが BSON と MessagePack の違いと欠点/利点を詳しく説明できますか?


パフォーマンスの高いバイナリ シリアル化形式のリストを完成させるために、Google の Protocol Buffers の後継となるGob もあります。ただし、言及されている他のすべての形式とは対照的に、これらは言語に依存せず、Go の組み込みリフレクションに依存しており、少なくとも Go 以外の言語用の Gobs ライブラリもあります。

4

6 に答える 6

213

// 私は MessagePack の作成者です。この回答は偏っている可能性があります。

フォーマット設計

  1. JSON との互換性

    その名前にもかかわらず、BSON の JSON との互換性は MessagePack に比べてあまり良くありません。

    BSON には、"ObjectId"、"Min key"、"UUID"、"MD5" などの特殊な型があります (MongoDB ではこれらの型が必要だと思います)。これらの型は JSON と互換性がありません。つまり、オブジェクトを BSON から JSON に変換すると、一部の型情報が失われる可能性がありますが、もちろん、これらの特殊な型が BSON ソースにある場合に限ります。1 つのサービスで JSON と BSON の両方を使用すると、不利になる可能性があります。

    MessagePack は、JSON との間で透過的に変換されるように設計されています。

  2. MessagePack は BSON より小さい

    MessagePack の形式は、BSON よりも冗長ではありません。その結果、MessagePack は BSON より小さいオブジェクトをシリアル化できます。

    たとえば、単純なマップ {"a":1, "b":2} は MessagePack では 7 バイトでシリアル化されますが、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、Protocol Buffers、Thrift、および Avro は RPC をサポートしています。しかし、BSON はそうではありません。

これらの違いは、BSON がストレージ用に設計されているのに対し、MessagePack はもともとネットワーク通信用に設計されていることを意味します。

実装と 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>();
    }
  1. MessagePack には IDL があります

    これは型チェック API に関連しており、MessagePack は IDL をサポートしています。(仕様はhttp://wiki.msgpack.org/display/MSGPACK/Design+of+IDLから入手できます)

    Protocol Buffers と Thrift は IDL を必要とし (動的型付けをサポートしていません)、より成熟した IDL 実装を提供します。

  2. 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
    }
于 2011-06-15T11:31:27.037 に答える
17

クライアント/サーバー環境がどのように見えるかに依存することに言及することは非常に重要だと思います.

メッセージ キュー システムやディスクへのログ エントリのストリーミングなど、検査なしでバイトを複数回渡す場合は、コンパクトなサイズを強調するためにバイナリ エンコーディングを使用することをお勧めします。それ以外の場合は、環境が異なるケースバイケースです。

一部の環境では、msgpack/protobuf との間で非常に高速なシリアライゼーションとデシリアライゼーションが可能ですが、そうでない環境もあります。一般に、言語/環境が低レベルであるほど、バイナリ シリアライゼーションがうまく機能します。高水準言語 (node.js、.Net、JVM) では、JSON シリアライゼーションの方が実際には高速であることがよくわかります。次に問題になるのは、ネットワーク オーバーヘッドがメモリ/CPU より多かれ少なかれ制約されているかということです。

msgpack 対 bson 対 プロトコル バッファに関して... msgpack はグループの最小バイトであり、プロトコル バッファはほぼ同じです。BSON は、他の 2 つよりも広範なネイティブ型を定義し、オブジェクト モデルにより適している可能性がありますが、これにより冗長になります。プロトコルバッファには、ストリーミングするように設計されているという利点があります...これにより、バイナリ転送/ストレージ形式のより自然な形式になります。

個人的には、トラフィックを減らす明確な必要性がない限り、JSON が直接提供する透過性に傾倒します。gzip されたデータを使用する HTTP では、ネットワーク オーバーヘッドの違いは、フォーマット間でさらに問題になることはありません。

于 2013-07-30T21:34:29.163 に答える
4

クイックテストでは、縮小されたJSONがバイナリMessagePackよりも高速に逆シリアル化されることが示されています。テストでは、Article.jsonは550kbの縮小されたJSONであり、Article.mpackは420kbのMPバージョンです。もちろん、実装の問題かもしれません。

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  
于 2012-11-05T22:34:20.800 に答える
1

さて、著者が言ったように、MessagePack はもともとネットワーク通信用に設計されていますが、BSON はストレージ用に設計されています。

MessagePack はコンパクトですが、BSON は冗長です。BSON は CURD (時間効率) 用に設計されているのに対し、MessagePack はスペース効率が高いことを意図しています。

最も重要なことは、MessagePack の型システム (プレフィックス) がハフマン エンコーディングに従っていることです。ここでは、MessagePack のハフマン ツリーを描画しました (リンクをクリックして画像を表示):</p>

MessagePack のハフマン木

于 2019-08-19T03:36:59.183 に答える