1. ホーム
  2. serialization

[解決済み] パフォーマントなエンティティシリアライズ。BSONとMessagePackの比較(JSONの比較)

2022-05-08 01:19:20

質問

最近見つけた メッセージパック は、代替の バイナリ のシリアライズ形式は、Google の プロトコルバッファ JSON も両者を凌駕しています。

また BSON シリアライズ形式は、MongoDBがデータを保存する際に使用する形式です。

について、どなたか詳しく教えてください。 BSONとMessagePackの違いと欠点は? ?


性能の良いバイナリー・シリアライズ・フォーマットのリストを完成させるだけです。また ゴブズ <ストライク GoogleのProtocol Buffersの後継となるものです。 . しかし <ストライク は、他のすべてのフォーマットとは対照的に、言語にとらわれず Goの組み込みのリフレクション また、少なくともGo以外の言語用のGobsライブラリもあります。

解決方法は?

// 私はMessagePackの作者であることにご注意ください。この回答は偏っている可能性があります。

フォーマット設計

  1. JSONとの互換性

    BSONはその名の通り、JSONとの親和性はMessagePackに比べてあまり良くありません。

    BSONには、"ObjectId", "Min key", "UUID" or "MD5" といった特殊な型があります(MongoDBはこれらの型を要求していると思われる)。これらの型はJSONと互換性がありません。つまり、BSONからJSONに変換するときに、いくつかの型情報が失われる可能性があるということです。もちろん、これらの特殊な型がBSONソースにあるときだけですが。一つのサービスでJSONとBSONの両方を使用することは、不利になる可能性があります。

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

  2. MessagePackはBSONより小さい

    MessagePack のフォーマットは BSON よりも冗長ではありません。その結果、MessagePackはBSONよりも小さなオブジェクトをシリアライズすることができます。

    例えば、単純なマップ {"a":1, "b":2} は、BSON では 19 バイトでシリアライズされますが、MessagePack では 7 バイトでシリアライズされます。

  3. BSONはインプレース更新に対応

    BSONでは、オブジェクト全体を再シリアライズすることなく、保存されたオブジェクトの一部を変更することができます。例えば、マップ {"a":1, "b":2} がファイルに格納されていて、"a" の値を1から2000に更新したいとしましょう。

    MessagePack では、1 は 1 バイトしか使用しませんが、2000 は 3 バイトを使用します。そのため、"b"は変更しないが、"b"は2バイト後退させる必要がある。

    BSONでは、1も2000も5バイトを使用します。この冗長性のため、"b"を移動させる必要はないのです。

  4. MessagePackはRPCを搭載

    MessagePack、Protocol Buffers、Thrift、AvroはRPCをサポートしています。しかし、BSONはそうではありません。

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

実装とAPI設計

  1. MessagePackは型チェックのAPIを持つ(Java、C++、D)

    MessagePack は static-typing をサポートしています。

    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
    }