Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Msgpack cli-tech-aid-2013

2,886 views

Published on

  • Be the first to comment

Msgpack cli-tech-aid-2013

  1. 1. MessagePack CLI @yfakariya
  2. 2. SIer でスキマを埋める仕事をしてます プログラミング歴≒.NET歴 API 周りとかの仕事が得意です ご縁があり翻訳とかしてます • 『.NET のクラスライブラリ設計』 • 『プログラミング .NET Framework』(第3版~)
  3. 3. MessagePack CLI のご紹介 • MessagePack とは • MessagePack CLI とは • 0.4.0 について • 今後の予定 • Deep Dive
  4. 4. バイナリ形式の自己型記述型データフォー マット • 数値やフラグを小さなバイトで表現可能 • 文字列中心だとそれほど変わらない • 画像を BASE64 化したりする必要がない • ストリーム自体に型情報を付与
  5. 5. さまざまな言語で実装 • つまり、バイナリ形式で他の言語と通信できる • 言語(https://github.com/msgpack/より) • C++ • Ruby • Java • CLI(C#,VB,F#,etc…) • JavaScript(Node.js) • Python • Lua • Erlang • Haskell • D • Go • Perl • Smalltalk • OCaml • PHP
  6. 6. だいたい Protobuf と同じ コンパクト • -31~127 までの整数は型情報付きで1バイト • bool、nil は 1 バイト • 要素数 15 以下の配列、map、バイト数 31 以下の 文字列(UTF-8)ヘッダは型情報込みで 1 バイト • つまり、フラグとか整数にするととてもコンパク ト
  7. 7. 都道府県と郵便番号と住所のレコード • MSKK の住所だとこんな感じ • 0x93, 0x0C, 0x97, …, 0xD9, 0x27,… FixArray3 (構造体の フィールド数 が 3なので) PositiveFixNum5 1 (JIS都道府県 コードを数値化、 ここでは13) FixStr7 (郵便番号7ケ タ、文字列とし て) この後7バイトが UTF-8の郵便番号 Str8 + バイト数 (0x27) 住所本体のUTF-8 文字列
  8. 8. Common Language Infrastructure 用の実 装 • C# だけでなく、VB も OK  動くけど、F# や Iron* や PowerShell 向きではない • Mono でも動く • Silverlight/WP7.1 でも動く  自動テストがないのがネック 公式 Msgpack リポジトリの一員 • https://github.com/msgpack/msgpack-cli Apache 2 ライセンス
  9. 9. シンプルな API • 『Framework Design Guidelines』訳した人として も頑張りました。 かなりはやい • 0.4.0 Beta2 では、protobuf-net ±15% 程度 他の言語のバインディング豊富 • https://github.com/msgpack • それぞれの言語に合わせた API
  10. 10. 本家 issue 128 対応 • bin 型の対応:文字列でないバイナリ型をサポー ト • str8 型の対応:ディクショナリのキーなどで多用 される、32~127 バイトの文字列のサイズ削減 • ext 型の対応:AP 固有の型情報をバイナリそのも のに埋め込むフレームワーク  別の言語や実装で読み込んだ時に、そのデータが特定 の「拡張型」を意図していたことがわかるように。
  11. 11. Issue 128とは • MessagePack の仕様は、C++ や Ruby との互換 性を考慮して、文字列とバイト列を区別していな かったが、それだと JavaScript なんかで結構困 る、と言う話に標準化で商売している人が入って きたりしてえらいことになったスレッド(特徴: 長い)  https://github.com/msgpack/msgpack/issues/128
  12. 12. パフォーマンスチューニング • 苦節1年、ようやくパフォーマンスを向上できま した。 • 違ったもの  ストリームの読み取り(によるバイト配列生成)がボ トルネック説  仮想メソッド呼び出しオーバーヘッド説 • 原因  Nullable<T> のオーバーヘッド • Nullable<T> の API を deprecated にして解消。。。
  13. 13. そもそも論 • 最初からパフォーマンスを指向していない実装 で、ベンチマークとか出されて比較されると割と つらい • 先を見越せる経験、熟慮、運が大事 プロファイラをあてにしすぎない • ボトルネックがなく、なんか遅いときには役に立 たない(Nullable<T> のオーバーヘッドとか出て こない)
  14. 14. プラットフォーム強化 • Xamarin.Android • Xamarin.iOS • .NET Micro Framework  Issue #7 • WinRT(現在は CoreCLR 対応版のみ) • Windows Phone 8 まずは動作確認レポート募集中です!
  15. 15. NuGet から Msgpack cli をインストールし てみてください! フィードバックお待ちしてます! • 日本語でツイートが手軽です。  Github の issue に英語でやってくれた方が、議論は深 まると思いますが Happy Hacking!
  16. 16. Serialization API • MessagePackSerializer<T> • SerializationContext MessagePackObject T Primitive API • Packer • Unpacker <<corresponds>> <<uses>> <<corresponds>> System.IO.Stream <<uses>>
  17. 17. MessagePack 型システムの CLI 表現 • 整数 • 浮動小数点(IEEE 823 2進) • バイナリ(0.4 以降は文字列と純粋バイナリを区 別) • 配列 • マップ(ディクショナリ) • 拡張型(0.4 以降) • 真偽値 • nil
  18. 18. 軽量な値型 型変換演算子による CLI/FCL プリミティ ブへの変換 特殊な型: • 配列:IList<MessagePackObject> • ディクショナリ: IDictionary<MessagePackObject, MessagePackO bject>
  19. 19. 値のバイナリ表現を格納するためのビット 列 • 8bit(UInt64) • Single/Double は適宜変換して返す オブジェクトを格納するためのフィールド • 参照型(Byte[]、String、IList<MPO>、 IDictionary<MPO,MPO>) • または値型フィールドのセマンティクスを表現す る「型オブジェクト」 default(MPO) == MPO.Nil
  20. 20. MessagePack ストリームと MessagePackObject の相互変換 • XmlReader/Writer、StAX 相当の役割 • コレクションの Unpack のステート管理 • エンディアンの対処 • パフォーマンス上クリティカルなレイヤ • 通信遅延の待機や複数ストリームの Aggregate、 バッファリングなどの機能は持たない  Stream クラスの役割と割り切っている
  21. 21. 素直な実装 • エンディアンの切り替え • できる限りコンパクトな表現を選ぶ  値1Lは int64 でなく PositiveFixNum1 PackerCompatibilityOptions • MsgPack issue 128 以前の実装が読めるバイナリ を吐く  バイト列を Raw 型(文字列かもしれないバイナリ)で 出力  Str8 を使わない
  22. 22. SubtreeUnpacker • コレクションの入れ子のステート管理を担当 • XmlReader.ReadSubtree() と同じ考え方 • 処理は ItemUnpacker に委譲 ItemUnpacker • ストリームの読み取りと解釈
  23. 23. パフォーマンスネック • MessagePackObject への Unpack • 現在 Unpack 中の状態(型は何バイトか、要素数 はいくつか、キーなのか値なのか…)を保持 最適化 • 泥臭い  メソッド呼び出しオーバーヘッド削減のため、T4 によ る「マクロ展開」(あまり効果がない気がするので、 リファクタリングするかも)  FixNum や Boolean 値の MPO コンストラクタオー バーヘッド削減のためのルックアップ配列
  24. 24. シリアライザ • 任意のオブジェクトと MessagePack ストリーム の相互変換 • API は少数  MessagePackSerializer クラス:ファクトリ  MessagePackSerializer<T> クラス:シリアライザの定 義  SerializationContext クラス:シリアライザのリポジト リ  SerializerGenerator クラス:シリアライザを DLL とし て書き出す
  25. 25. シンプル指向 • 循環参照はサポートしない  サポートしても他の言語バインディングがサポートし ていない • したがって、ISerializationFormatter ではないし、 XmlObjectSerializer でもない • 限定されたカスタマイズポイント  IPackable/IUnpackable と SerializationContext
  26. 26. ISerializable 相当の低レベルインターフェ イス Packer/Unpacker を受け取り、自分のイン スタンスフィールドの状態を読み書きする Java 版との機能的互換性が主な目的
  27. 27. シリアライザの構成を表現 • 静的な Default  アプリケーション内のシングルトン • インスタンスとして引き回し可能 • DI コンテナフレンドリではないが、Composition Root で構成して、Default に突っ込んでおくのは 可能 • フレームワークなどを実装する場合、フレーム ワーク内で SerializationContext を保持してお き、設定の Isolation が可能
  28. 28. シリアライザのリポジトリを保持 • 型 T をキーにして、MPS<T> のインスタンスを保 持 • このリポジトリを直接変更することで、任意の MPS<T> 実装でシリアル化をカスタマイズ可能 • FCL の基本型のシリアライザが既定で登録済み (パフォーマンス向上のため)
  29. 29. MPS<T> を動的に生成 • AutoMessagePackSerializer<T>  動的生成 MPS<T> の基本構成  対象の型に依存しないジェネリック処理を実装 • 動的生成  T のフィールド/プロパティに読み書きに特化したコー ド生成  ボックス化の削減  JIT コンパイルによるパフォーマンス向上
  30. 30. Pack と Unpack で動作が異なる • Pack は SerializationContext の設定によって、オ ブジェクトをフィールド値の配列にするか、マッ プにするのかが異なる  既定では配列(他の言語に合わせている)  Map の方がデータ的に堅牢 • Unpack は配列でもMapでも来たものを受け入れ る
  31. 31. コレクションの Unpack • IEnumerable<T> 派生型の読み取り専用フィール ド/プロパティの場合、メンバー宣言型が Add(T) を宣言していれば、それを使用して Unpack 可能 • つまり、  public IList<string> Foo{get{…}} をサポートしている。
  32. 32. コード生成戦略 • 基本は Reflection.Emit  MPS<T> 実装型にフィールドを生成できるため  T 型の各フィールド/プロパティ用の MPS<Tn> を フィールドに保持 • Silverlight4 用の DynamicMethod モード  T 型の各フィールド/プロパティ用の MPS<Tn> は、実 行時に SerializationContext からルックアップ • WindowsPhone/WinRT 用の ExpressionTree モー ド  ルックアップ
  33. 33. カスタム属性なしでも「空気を読んで」対 応 [Serializable] がついている場合、 [NonSerialized] を尊重 [DataContract] がついている場合、 [DataMember] を尊重 • Id は 0 ベース • 互換性オプションで 1 ベースにもできる (protobuf-net との切り替えを容易に)
  34. 34. ストリームに Nil があった場合に対処方法 を、プロパティ/フィールドに付与するカ スタム属性で指定可能 • Null にする(非 Nullable の値型だとエラー) • フィールドの値をいじらない • 常に例外
  35. 35. 実験中 コード生成とコンパイルのコストを省略す るために、MPS<T> を事前にファイルに 出力する機能 • AssemblyBuilder.Save() するだけ

×