msgpack-erlangのはなし

この記事は Erlang Advent Calendar 2014 の三日目の記事です。

MessagePackというシリアライゼーションのフォーマット
がある。これはまあまあ有名じゃないかもしれないけど、今をときめく fluentd の裏側で使われているプロトコルだ。この手のシリアライザは多種多様で、圧縮まで考えると歴史的にも沢山あって死屍累々の歴史でもある。モダンなやつだとAvro, Thrift, ProtocolBuffers などがあるが、サイズ、速度、柔軟性のバランスを考えるとかなり独特な位置にある。興味があるひとはTwitterでMessagePackってつぶやいてみると作者たちが釣れるかもしれない。今日はこの Erlang/OTP での実装について話をしよう。


使い方

基本的にはこれを単体で使うことはないだろうと思うが、簡単に試したいかたは次のようにすればよいだろう。システムに Erlang/OTP (R15B ~ 17.x) と git がインストールされていることが前提だ。

$ git clone git://github.com/msgpack/msgpack-erlang
$ cd msgpack-erlang
$ ./rebar compile
$ erl -pa ebin
> Bin = msgpack:pack([<<"spam">>, <<"ham">>, <<"egg">>, 42]).
<<148,164,115,112,97,109,163,104,97,109,163,101,103,103,42>>
> msgpack:unpack(Bin).
{ok,[<<"spam">>,<<"ham">>,<<"egg">>,42]}

他にもいくつかAPIがあり、ドキュメントはないが、関数そのものは4つしかない。 msgpack.erl をみれば概要がわかるだろう。ちなみに Erlang/OTP 専用になるが、 "msgpack:term_to_binary/1" と "msgpack:binary_to_term/1" という便利関数も用意している。これは、 MessagePack の新仕様の拡張型を使って、ErlangのTermを全部エンコードできるようにしたものだ。これを使えば、 ナマのMessagePackでサポートしているプリミティブなErlang Termはそちらに変換され、 pid() などどうにもしにくいものは t2b なり b2t に部分的にフォールバックしてくれるというスグレモノだ。ちなみにコレを使っている人はまだみたことがない。速いかどうかは知らない。

自分のErlang/OTPのソフトウェアに組み込みたいときは、 rebar.config に次のように書くとよいだろう。

{deps, [
        {msgpack, "0.*",
         {git, "git://github.com/msgpack/msgpack-erlang", {tag, "0.3.2"}}}
       ]}.

事例

  • 今をときめくアドテクの会社、VOYAGE GROUPで使われているとのこと
  • 某社で内部のプロトコルで使われているそう
  • たまに海外からメールが来る

今の実装の問題点

  • NIF版に手をつけられていない。拡張型が入った時点で一旦外していたのだが、戻ってこられず…
  • jiffyやjsxインターフェースを捨てたいが捨てられない
  • 最適化?なにそれ?
  • テストが足りてない

今後の方向性

− Pull Request がいつの間にか来てたので対応したい

コントリビュート

こちらまで。Apache 2ライセンスに同意していただくことが必要。OSSのソフトウェアを開発する仕事をしているくせに、OSSの開発にあまり時間を割けていないというみっともない状態なので、メンテナが増えてくれると嬉しいなあ…

歴史とポエム

いま改めて検索してみると、最初の実装を発表したのは5年以上も前になる。最初のコードはわずか300行ちょっとの1ファイルで、シリアライザとデシリアライザが全部入ってしまって、Erlangのパターンマッチすげえ!と感動したのを5年ぶりに思い出せた。当時はまだ僕はErlangを始めたばっかりで…(以下ポエム)

それが、8ヶ月後には公式ライブラリの仲間入りをして…それも4年前のことであるから、思えば遠くまで来たもんだ。