Developer's Blog

XML より JSON より MessagePack が便利です

こんにちは。開発担当の森本です。

今回は、Fenrir Pass Connect を支える技術にちょっと関係のある、 web などを介してデータを交換するときの話をしたいと思います。

データ構造の共通化 → 実装も共通化できる

プログラム間、端末同士、Web 経由などでデータを送ったり送られたりするときに、データは決まったフォーマットで送られる必要が有ります。

たとえば、今表示しているこのページでは、本文は HTML、画像は PNG などのバイナリフォーマット、web API との連携などは JSON や XML、スタイルシートや JavaScript はそれぞれ独自のテキストフォーマットが使用されています。
一般的なプロダクトでは上記のうち、XML や JSON が使用される事が多いと思います。

これらのフォーマットは普及率が高いため情報も多く、多くの処理系で枯れて安定した実装があるため、 Sleipnir でもあちこちで使用されています。

扱う情報の肥大化 → より効率の良いフォーマットが必要

ただ、web でいろんなことができるようになり、ネットワーク速度も改善するにつれて、XML や JSON では辛い状況が生まれてきています。

Fenrir Pass Bookmark においても、扱うブックマーク数メガバイトに達することも多く、モバイル端末では構文解析することすら苦しい状態になっています。
適当なバイナリフォーマットを作ればサイズも解析速度も改善しますが、全ての処理系で実装を書く必要が発生してしまい、これも険しい道のりとなってしまいます。

なにか、共通化されていて、JSON みたいに楽に使用できて、サイズが小さくて処理速度が速いフォーマットって無いものでしょうか?

ここで華麗に MessagePack が参上!

これらの問題は、MessagePack を使用すれば一気に解決することができます!

C++ の実装の話ですが、構造体に直接シリアライズ・デシリアライズでき、無駄なコピーが起こらないように、テンプレートを駆使して実装されており、JSON とは比べものにならない速さです。

// データ構造
struct mystruct {
    std::string m_str;
    std::vector<int> m_vec;

    MSGPACK_DEFINE(m_str, m_vec);
};
 
int main(void) {
    mystruct original_data;
    mystruct clone_data;

	// シリアライズ
    msgpack::sbuffer sbuf;
    msgpack::pack(sbuf, original_data);

	// デシリアライズ
    msgpack::unpacked msg;
    msgpack::unpack(&msg, sbuf.data(), sbuf.size());
    msgpack::object obj = msg.get();
    obj.convert(&clone_data);
}

このように、非常に簡単に使用できます。

また、生成されるデータも JSON に比べて半分程度になりますが、JSON と相互に変換できるほど柔軟な表現ができます。


{“a”:null,”b”:10,”c”:[20],”d”:”30″} <= 35byte        ↓ 84 a2 61 c0 a2 62 0a a2 63 91 14 a2 64 a2 33 30 <= 16byte [/text] こんな感じで、半分以下のサイズになります。 対応している処理系も Ruby, Python, Perl, C, C++, Java, Haskell, JavaScript, D, C#, Erlang, Scala, Go, Lua, node.js, OCaml, PHP と素晴らしい状態です。

まとめ

実は Sleipnir 3 では、すでに速度が必要な部分で MessagePack を使用しており、良い感触を得ています。
現在も、もっと使用される範囲を広げ、プロダクトが改善できるよう頑張っていますので、ご期待下さい。

ソーシャルアカウント

Copyright © 2019 Fenrir Inc. All rights reserved.