MessagePack 0.3.0 リリース!

バイナリシリアライズ形式MessagePackのバージョン0.3.0をリリースしました。C API が大幅に充実、ストリームデシリアライザとメモリゾーンの効率化など。

MessagePackのプロジェクトページができました:http://msgpack.sourceforge.jp/


シリアライズフォーマットには完全な互換性があります。
APIソースコードレベルではほぼ互換性がありますが、バイナリレベルでは互換性はありません。ライブラリは0.2.2と共存できますが、新しいAPIを利用するには再コンパイルが必要です。

  • ドキュメント整備
  • C APIの追加
  • モリゾーンの機能強化
  • C/C++のストリームデシリアライザの効率化
  • シンプルなバッファの実装を標準添付
  • Ruby API で MessagePack.unpack_limit を追加
  • gemパッケージがシンプルに

C APIの追加

オマケくらいの機能しかなかったC APIですが、C++ APIと同じくらいの機能が使えるようになりました。

  • インライン化されたシリアライザ(msgpack_pack_XXX)
  • ストリームデシリアライザ(msgpack_unpacker)
  • オブジェクトAPI(msgpack_object)
  • モリゾーン(msgpack_zone)

モリゾーンの機能強化

0.2.2でも実装されていた msgpack::zone ですが、0.3.0でゾーンからのメモリを確保する速度が超大幅に高速化しました。
msgpack::zone(msgpack_zone)は複数のスレッドから同時にメモリ確保できない代わりに、malloc(3)よりも圧倒的に高速にメモリを確保することができます。ゾーンを解放すると、そのゾーンから確保していたメモリは全部解放されます。
また任意の関数を登録しておくと(複数可)、ゾーンを解放するときに呼び出されます。これを利用してゾーンを解放すると同時に様々な後始末を漏れなく行わせることができます。


C++ API では msgpack::zone からオブジェクトを確保(new)することができます。msgpack::zone を開放するときに一緒にdeleteされます。コンストラクタに引数を渡すことができ、メモリゾーンを解放すると同時にデストラクタも呼ばれます。
C++ の msgpack::zone* と C の msgpack_zone* は相互にキャストして使うことができます。C++のプログラムからCのプラグインを呼び出したい場合などに便利です。


以下のようなシナリオで便利に使えると思います:

  1. ネットワークやファイルからデータを読み込む
  2. ストリームデシリアライザを使ってメッセージをデシリアライズする
  3. ストリームデシリアライザからゾーンを取り出す(デシリアライズされたオブジェクトはゾーンが解放されるまで有効 => ゾーンと一緒に持ち運ぶ)
  4. シリアライズされたオブジェクトを使って、いろいろと処理する
    1. 処理の最中で必要なメモリはゾーンから確保する
    2. 後始末が必要になったら、その都度後始末関数をゾーンに登録しておく
  5. ゾーンを解放する

C++の場合はゾーンを取り出したら std::auto_ptr やスマートポインタに入れておくと便利です。

C/C++のストリームデシリアライザの効率化

ストリームデシリアライザは内部にバッファを持っており、データをバッファにデータを追記していくと同時にデシリアライズを進めていくことができます。このバッファの扱いを効率化しました。
参照カウンタを使って複数のメッセージが1つのバッファを共有する形になっています。小さいメッセージが大量に押し込められてきたときに、メモリ使用量が大幅に削減されます。
使い方は 0.2.2 と変わらず、msgpack::zone を開放すると同時に後始末されます。


msgpack::zone と組み合わせたストリームデシリアライザの使い方は、サンプルコードを参照してください。

シンプルなバッファの実装を標準添付

シリアライズするとき、バッファは自分で実装しなければなりませんでしたが、0.3.0ではmalloc/reallocを使ったシンプルなバッファの実装を標準で添付しました。C API では msgpack_sbuffer、C++ API では msgpack::sbuffer を利用できます。
msgpack::sbuffer* と msgpack_sbuffer* も相互にキャストして使うことができます。

MessagePack.unpack_limit(data, limit)

Ruby API で、バイト数を制限してデシリアライズするメソッドを追加しました。

gemパッケージがシンプルに

newgemをベースにして作っていたgemパッケージを、cutagemをベースにして作り替えました。