読者です 読者をやめる 読者になる 読者になる

RubyKaigi2010でトークしてきました - The MessagePack Project

つくばで開かれたRubyKaigi2010で、多言語間通信ライブラリ MessagePack についてLTしてきました。
音声付きの動画をニコニコ動画で見られます(スバラシイ!)。ぴったり5分に収まりました^^;



Twitterを見る限りでは評判も良かったようで、ひとまず安心しています。

説明が足りなかった部分もあるので、ここで補足しておきます。

JSONと比べてどれくらい小さくなるの?

ある日のTwitterのpublic_timelineを使って比較してみたところ、JSONでは31KBだったものが、MessagePackでシリアライズし直すと25KBになり、約19%削減されました。

ただミニブログサービス「Amebaなう」に…等々の話にもあるように、「MessagePackを使えば必ず大幅にサイズ圧縮に成功する」という訳ではないです。
例えば、大半がASCII文字列で埋まっているようなJSONはほとんど小さくなりません。バイナリデータを含んでいたり(JSONではBASE64などでエンコードする必要がある)、複雑な構造を持つデータが特に小さくなります。


Amebaなうでの事例はjust do neetさんのブログに詳しく取り上げていますので、ぜひご覧ください:LuceneのインデックスにStoreするデータをMessagePackで圧縮してみた

なぜJSONと比べて小さくなるの?

よく使われるデータほど少ないバイト数でシリアライズするようになっているためです。他にも型を表すバイトにデータ自体を埋め込んでサイズを削減するなどの工夫をしています。
例えば-31〜128の小さい整数は1バイト、要素数が15個までの小さな配列や連想配列1バイトで表します。truenullなどの要素も1バイトです。

極端な例では、{"a":true}という連想配列は、JSONでは10バイトも必要ですが、MessagePackでは4バイトで済みます。
MessagePackの詳しい仕様については、MessagePack format specificationを参照してください。

なぜJSONと比べて速いの?

JSONやXMLはテキストフォーマットなので、文字列のエスケープ処理(やエスケープ解除処理)に時間がかかります。文字列が長ければ長いほど、線形に処理時間が増えていきます。
このため、長い文字列を含んだデータではMessagePackの方がずっと高速になります。
大きな画像データを扱う用途にJSONを使う気にはなりませんが、MessagePackなら効率よく扱えます。画像にメタデータを付与して保存しておきたい場合などなど。


RailsのログファイルをMessagePackで超高速解析!もご覧ください。

RPCのサーバ側はどう書くの?

↓これで動きます。

require 'msgpack/rpc'    # gem install msgpack-rpc

class KVServer
  def initialize
    @hash = {}
  end

  def get(key)   # publicなメソッドがRPCで呼べるようになる!
    @hash[key] # @hashからkeyを取り出して返す
  end

  def set(key, value)
    @hash[key] = value  # @hashにkey-valueをセット
  end
end

# MessagePack::RPC::Server#listen(アドレス, ポート番号, インスタンス)
svr = MessagePack::RPC::Server.new
svr.listen('0.0.0.0', 18800, KVServer.new)
svr.run   # イベントループ開始

publicなメソッドをリモートから呼び出すことができます。
これで簡単なKey-valueストアができました。全部で54行もあれば分散KVS(レプリケーション機能付き)を実装することができます。

コネクションプーリングはどうやって使うの?

↓こうやって使います。

require 'msgpack/rpc'    # gem install msgpack-rpc

# SessionPoolを作成
$ws = MessagePack::RPC::SessionPool.new

# セッションを取得(初めてなら自動的に作成される)
session = $ws.get_session("127.0.0.1", 18800)

# Client < Session
p session.call(:get, "key1")

WebSocketでブラウザにプッシュ配信する - MessagePack-RPC+Rev-WebSocketで具体的な使い方を紹介しています。

コネクションが切断されたらどうなる?

自動的に再接続します(Thriftとは違って)。

どこで使われているの?

実はあなたのそばにもMessagePack。

もっと詳しく知るには?

MessagePackのWikiや、Twitter#msgpackタグをウォッチしてみてください。
ソースコードリポジトリgithubにあります。 
RDocはここです:シリアライズ RPC


Ruby版のメンテナンスは私が行っています。何か疑問などなどあれば @frsyuki までどうぞ^^;