nuits.jp blog

C#, Xamarin, WPFを中心に書いています。Microsoft MVP for Development Technologies。

IoC コンテナ パフォーマンスバトル on Xamarin in 2017

少し前に、PC上でのIoCコンテナのパフォーマンス調査を行いました。

www.nuits.jp

今回はXamarin上で調査しましたので、その情報を共有したいと思います。

それでまずは結果から見てみましょう。
まずはUnityの性能を100%としたときの評価グラフです。

f:id:nuitsjp:20170127183615p:plain

具体的な数値は以下のとおりです。

Container Singleton - Registartion Singleton - Resolve Transient - Registartion Transient - Resolve
DryIoc 75% 1169% 385% 2255%
SimpleInjector 69% 527% 7% 2231%
AutoFac 64% 104% 19% 184%
AutoFac Lambda 96% 110% 5% 1236%
Unity 100% 100% 100% 100%

SimpleInjectorは相変わらず早いですが、DryIocが素晴らしい速度を出していますね。
というわけで、詳細なデータを掘り下げてみて行ってみましょう。

前提条件

  • iPhone 6S
  • iOS 10.2
  • Xamarin 4.2.2.11
  • Xamarin.Forms 2.3.3.180

評価内容

  • Singlton時のコンテナ登録時間
  • Singlton時のインスタンス取得時間(10万インスタンス
  • インスタンス都度生成時のコンテナ登録時間
  • インスタンス都度生成時のインスタンス取得時間(10万インスタンス

評価結果

以下が評価結果です。
数値はミリ秒になります。
それぞれResolveは10万回実行しています。

Container Singleton - Registartion[ms] Singleton - Resolve[ms] Transient - Registartion[ms] Transient - Resolve[ms]
new Operator 0.17 21.72 0.03 215.25
DryIoc 21.07 22.61 0.17 1557.74
SimpleInjector 23.01 50.18 9.07 1574.58
AutoFac 24.86 253.96 3.56 19090.53
AutoFac Lambda 16.51 241.12 13.64 2842.19
Unity 15.86 264.31 0.67 35124.85

ざっくり分けると性能的には

  • 第一集団
    • DryIoc
    • SimpleInjector
  • 第二集団
    • AutoFac Lambda
    • Unity

になります。
さて、PC上での場合性能差ははっきりいってほとんど人にとって趣味のレベルでしたが、Xamarin上だと少しきにかかります。
今回は10万回のResolveでテストしました。
生成しているオブジェクトは13種類です。
この時、Unityの都度生成が0.35秒、AutoFacの非Lamdaが0.19秒かかっています。
ケースによっては性能が気になるレベルであるかもしれませんね。

また、コンテナへの登録も13種類のクラスを登録しているだけですが、20[ms]前後かかっています。
これはアプリケーションの初期化時の遅延につながります。
大きなアプリケーションの場合、愚直にコンテナ登録をしてしまうと、体感へ悪影響がでてくるかもしれません?そんな大きなアプリあまりないかもしれませんが。

動作環境・開発状況比較

Container Nuget Downloads Latest Release Latest Commited PCL .NET Standard Prism
AutoFac 3,441,183 2016/11/23 2017/1/3 1.1
DryIoc 91,736 2017/1/12 2017/1/27 1.0
SimpleInjector 811,212 2016/12/2 2016/11/27 1.0 / 1.3 -
Unity 4,900,116 2015/10/6 2016/5/18 -

DryIocは、「DryIoc」と「DryIoc.dll」の二つのDownload件数の合算値になっています。
無印側はNuGetを適用するとプロジェクト内部にコンテナのコードが追加されます。
それに対して、DryIoc.dllはアセンブリレベルでの参照になります。
なので無印はPCLのプロファイルや.NET Standardのバージョンなどに依存せず利用できる可能性が高いのですが、フレームワークから依存されていた場合は、DryIoc.dll側を参照する必要があります。
例えばPris,DryIoc.Formsとか。
最も.NET Standardの対応バージョンが1.0ですし、現時点でPCLのProfile259(UWPやWin8系も含めるやつ)でも動作しているので.dllを使って問題ないでしょう。

なお、StructureMapも本来は評価したかったのですが、StructureMap自体は.NET Standard 1.3向けに提供されているのに内部で.NET Standard1.6に依存しているため、今回は評価はあきらめました。。。

総括

とりあえず、Unityが不安なPrism.FormsユーザーはDryIocかAutoFacおすすめです。
実績自体はAutoFacの方が多いですがDryIocのパフォーマンスは魅力的ですね。 なお機能的な差異については詳細はまだ未調査ですが、最低限IoCコンテナとして求められる範囲はいずれも対応されています。

ちなみに今回のコードはこちらで公開しています。

github.com

私は最近のまともなスペックのAndroidやWin10mを持っていないので、お持ちの方はどなたか実験して記事を書いていただくか、面倒ならリリースビルドしてスクショを投げていただけるでもしていだけると嬉しいです。

という訳で今回はここまで。
それではまた!