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.

Net fringejp2016

1,580 views

Published on

.NET Fringe Japan 2016 slides about MsgPack for CLI and week end FOSS development (Japanese).

Published in: Technology
  • Be the first to comment

Net fringejp2016

  1. 1. MessagePack for CLIと そこから学ぶ.NETの マルチプラットフォーム対応 .NET Fringe Japan 2016 藤原 雄介
  2. 2. 自己紹介 • 藤原 雄介 @yfakariya • MVP for Visual Studio and Development Technologies 2015- • .NET 系の本をいくつか翻訳したり、OSS 書いたりしてます • 『.NETのクラスライブラリ設計』『プログラミング.NET Framework』等 • BotR、Azureのドキュメントetc. • Msgpack for CLIコミッタ、ちょこちょことPR
  3. 3. 今日のお題 • クロスプラットフォームな.NETのOSSシリアライザーを週末に 作った話 • 作ったものの説明 • クロスプラットフォーム実装の事例 • ライブラリ、ビルド、テスト
  4. 4. 余談:週末OSSるには • 好きな分野でやる • 結構好きな分野って重ならないもの • あえてメジャーどころに手を出さない • 他に人に追い抜かれてやる気が、とかない • シリアライザーとか DispatchProxy とか他にやる人いない……はず • 完璧を求めず、面の皮を厚くする • バグがあった? OK直すよ(でも今日は寝る) • コミット履歴が汚い? 知らんがな • まずはやってみる • 周囲の理解を得る
  5. 5. MessagePack for CLIとは
  6. 6. シリアライザーライブラリ • MessagePack for CLIというシリアライザーライブラリ • シリアライザーとは何か、という哲学的な話はしません • 参照でつながった一連のオブジェクト(オブジェクトのグラフ構造) を一直線(シリアル)なバイト列に変換する(そして戻す)コンポー ネント
  7. 7. MessagePack for CLI • 相互運用可能なバイナリ形式エンコーディングである MessagePack(msgpack)の.NET実装 • エンコーダ + シリアライザー • Msgpack • バイナリ形式のJSONのようなもの • バイナリ形式:ProtocolBufferやAvroなど • Fluentdで使っているフォーマット • CLI: Command Language Infrastructure, NOT CommandLine Interface
  8. 8. msgpackエンコーディングのメリット • JSON に比べて • 数値のサイズが劇的に小さい • 特に、-31~127の範囲は 1 バイト • 文字列のサイズは同じ • どちらもUTF-8 • 配列のサイズが劇的に小さい • ヘッダー(1~5バイト) + 要素 • ブレがない • =と:間違えたり、”つけ忘れたりといった亜種がない • デシリアライザーの実装が楽
  9. 9. XPLAT <dependencies> <group targetFramework=".NETFramework4.6" /> <group targetFramework=".NETFramework4.5" /> <group targetFramework=".NETFramework3.5" /> <group targetFramework="WindowsPhone8.0" /> <group targetFramework="MonoAndroid1.0" /> <group targetFramework="MonoTouch1.0" /> <group targetFramework="Xamarin.iOS1.0" /> <group targetFramework=".NETStandard1.1" /> <group targetFramework=".NETStandard1.3" /> +Unity • Full • Mscorlib only MsgPack.nuspec
  10. 10. 動作例(地味注意)
  11. 11. シリアライザーの設計
  12. 12. (たぶん)一般的な シリアライザーの構成要素 Type Introspector Encoder/DecoderCache Validator API Type Model Mapper
  13. 13. Type Introspector / Type Model • シリアライズする対象の型をスキャン • シリアライズ対象のプロパティやフィールドを列挙 • 特別扱いする型の判定 • コレクション • String • プリミティブ • 内部的に処理しやすいオブジェクトモデルに変換しておく
  14. 14. Mapper • Type Modelをシリアライズ先のエンコードの表現に変換 • JSONなら、Number、String、Bool、Array、Object、Nullと対応づけ る • MsgPackの場合、さまざまな整数型、Real32、Real64、Array、Map、 Ext、Nil、Bool
  15. 15. Encoder / Decoder • 実際のエンコードを行う • テキスト系(JSONやXML)なら文字エンコーディングも行う • バイナリ形式の場合、マッピングした型をそのまま書き出す • ただし、MsgPackの場合は整数値の圧縮表現を処理する • -31~127の整数→そのまま書き出す • それ以外の整数:「型ヘッダー+数値のビット表現」で書きだす
  16. 16. Validator • デコードするバイト列は、そもそも不正な形式かもしれない • デコードしたデータは、デシリアライズ(逆シリアル化)でき ない形式かもしれない • これらの検証処理が必要
  17. 17. Cache • シリアライザーの内部オブジェクト群の構築はそれなりにコス トがかかる • 型(とオプション構成)に対して一意であるため、一度作れば 使いまわすことができる • 複数の型から使用される型もあるので、結構有効 • ユーザーが自前のシリアル化ロジックを実装したい場合、その 登録先となりうる。
  18. 18. API • これまでの要素を内部に隠蔽 • ユーザーにとって使いやすいインターフェイスを提供 • 後方互換性を確保 • 特定の標準インターフェイスへの準拠
  19. 19. シリアライザーの構成要素 Type Introspector Encoder/DecoderCache Validator API Type Model Mapper SerializationContext MessagePackSerializer SerializerAssemblyGenerator SerializerCodeGenerator *Attribute AbstractSerializers.* GeneratedSerializers.* [Un]packHelpers One More Things MessagePackObject TypeInfoEncoder SerializationTarget SerializationMember AbstractSerializers.* GeneratedSerializers.* [Un]packHelpers Packer Unpacker One More Things SerializerBuilder
  20. 20. 設計コンセプト • コンテキスト • 特別扱いの許容 • 多くの値型、コレクション型、Null許容型、Tuple • コード生成
  21. 21. コンテキスト • キャッシュと設定を保持するインスタンス • そこを見れば必要なものはある • DefaultContext • 多くの場合、コンテキストインスタンスの作成や管理はしたくない • 既定のインスタンスをグローバルに用意(使用は完全に任意) • ここに依存はしない(No God)
  22. 22. 特別扱いの許容 • 単一の汎用実装は魅力的だが、複雑すぎる • 特別扱いするとある意味で楽 • 値型(Nullable<T>を含む):多くの場合、メンバーごとのマッピン グよりも独自表現が適切(例:DateTime) • コレクション:あえて内部構造にアクセスしないことで汎用化(例: リンクリストや循環キュー)。GetEnumeratorとAddを使用 • 文字列/バイト列:IEnumerableだが直接マッピング可能、エンコー ディング • Tuple:意味論的にヘテロ型配列
  23. 23. コード生成 • リフレクションはあまり速くない • 実行時のボックス化を避けたい • ソースコードが吐けると無理が効く • ビルドプロセスに組み込める • ステップ実行できる
  24. 24. コード生成の問題 • 技術ごとにサポートするプラットフォームが異なる • Silverlightは? • ※開発当初はSilverlight3/4がまだ息をしていた • WinRTは? • AOT をフォローできるか(事前生成できるか) • strategy patternで逃げる • プラットフォームに合わせた実装 • 無理のない範囲で抽象化
  25. 25. コード生成のリストラクチャリング • LCG:Silverlightの旧バージョンと共にさようなら • ExpressionTree:Silverlight5とWin8 SLの不人気と共にさようなら • 式ベースなので、他の技術(Reflection.EmitやCodeDOM)との差異が著し くつらかった • ここはリフレクションでも十分だと考えた • CodeDOM:更新停止、.NET Core非対応 • RoslynのSyntaxFactoryに絶賛移行中 • そもそもコード生成しなくてもいい部分はコード生成しない • PackHelpers、UnpackHelpers
  26. 26. XPLAT 実装 テスト パッケージング
  27. 27. XPLAT実装の一般論 • XPLATにできないところ • プラットフォーム依存の強いところ • I/O、スケジューリング等 • 「OSの色が出るところ」:GUI 等 • とはいえ、I/OやスケジューリングはランタイムBCL/FCLやPALが吸 収 • アルゴリズムやインメモリデータ構造はXPLATにしやすい
  28. 28. XPLATにできそうもないところ Type Introspector Encoder/DecoderCache Validator API Type Model Mapper SerializationContext MessagePackSerializer SerializerAssemblyGenerator SerializerCodeGenerator *Attribute AbstractSerializers.* GeneratedSerializers.* [Un]packHelpers One More Things MessagePackObject TypeInfoEncoder SerializationTarget One More Things SerializerBuilder SerializationMember AbstractSerializers.* GeneratedSerializers.* [Un]packHelpers Packer Unpacker ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔
  29. 29. 悪魔は細部に宿る • コード生成は前述のとおりポータビリティがない • リフレクションAPIには、実はポータビリティがない • 過去のAPI設計の誤りの清算がしたかった? • SILVERLIGHTとかUWPとか • .NET Standard 1.5ならだいぶまし
  30. 30. .NET Platform Standardで解決 • しない • .NET Fx 3.5、Silverlightは対象外(Unityもねは解決しそう) • .NET Standard 1.5なら解消とはいうが • .NET 4.6.2 or .NET Core 1.0以上で「.NET Standard 1.5」 • .NET Standard 2.0に対応する.NET Fxは4.6.1から
  31. 31. AOT • JITとは異なるところがまだ多い • Reflection.Emitとかできない • シリアライザーは特殊なので秘孔をつきやすい(?) • constrained.コールで死ぬ class Foo<T> where T : IDictionary<K,V> { int Bar(T dic) => dic.Count // ExecutionEngineException } • 複雑めのジェネリック引数で死ぬ • DllImportしているCRTが引っかかる
  32. 32. 現実 Type Introspector Encoder/DecoderCache Validator API Type Model Mapper SerializationContext MessagePackSerializer SerializerAssemblyGenerator SerializerCodeGenerator *Attribute AbstractSerializers.* GeneratedSerializers.* [Un]packHelpers One More Things MessagePackObject TypeInfoEncoder SerializationTarget One More Things SerializerBuilder SerializationMember AbstractSerializers.* GeneratedSerializers.* [Un]packHelpers Packer Unpacker ✘ ✔ ✔✘ ✘ ✘ ✘ ✘ ✘ サポートできないAPI Collections.Concurrent.* Threading.* TypeCode Reflection.* Reflection.* AOT Reflection.* ✔ Reflection.* CodeDom.*
  33. 33. 解決策 • プロジェクトを分ける • Net3.5/4.5/4.6、Unity(corlib only/Full)、Xamarin.Android、 Xamarin.iOS、 Silverlight5/8、.NET Standard 1.1/1.3 • #if • 意外と組み込みのコンパイラー定数がある(SILVERLIGHT、UNITY_xx、 NETSTANDARD1_x) • NETSTANDARD1_X、.NET Core Dev Tools Previewのcsprojだと組み込まれてない ので注意 • きっとみんな持ってるReflectionAbstractions
  34. 34. コードの例
  35. 35. テスト • シリアライザーは幸いにもテストの自動化が容易 • 副作用がない • 手でテストとかやってられないというより、出来ない • 入浴中や食事中でも実行できる
  36. 36. テストのやり方 • パターンと境界値によるケースの抽出、実行 • 型 • コード生成の種類 • 組み合わせ・入れ子のパターン • 本当はここは間引くべき • 今はT4でコードを生成 • 一番パターンの多い環境で18,345メソッド、少ない環境だとそ の半分くらい • .NET 3.5、.NET 4.6、WinRT、WP8、Unity.iOS、Xamarin.iOS
  37. 37. テスト環境 • メイン • デスクトップPC • iOS ビルド+テスト • Mac mini • iPad mini • CI • AppVeyor(OSS plan)
  38. 38. テストツール • フレームワーク • NUnit • NUnitLite(Xamarin) • NUnitLite ベースのツール(Unity) • UniRx のツールを移植・改造 • MSTest(WP、UAP)
  39. 39. テスト対象プラットフォーム プラットフォーム テスト環境 Xamarin Android NUnitlite Xamarin iOS NUnitlite .NET Standard 1.1 MSTest .NET Standard 1.3 MSTest .NET Standard 1.3 + AOT* MSTest プラットフォーム テスト環境 .NET 3.5 NUnit Unity(mscorlib only) n/a Unity NUnit + ツール .NET 4.5 n/a .NET 4.6 NUnit Silverlight 5 n/a Windows Phone 8 Silverlight MSTest * .NET Standard 1.3 の UAP プロジェクトを テスト用に作り、ネイティブコンパイルして実行
  40. 40. テストの例
  41. 41. ビルドとパッケージング • .nuspecは手書き • ビルドは簡単なps1スクリプトで • PowerShell Coreで動くのかどうかは未検証…… • 基本はMSBuild(というか.sln)べったり • .NET用.sln • .NET 3.5用.sln • Xamarin用.sln • WinRT/WP/Silverlight系用.sln • 最近はAppVeyorにお任せ
  42. 42. ビルドの例
  43. 43. Q&A

×