Xamarin 製アプリのメモリのプロファイリングは、
を意識する必要があります。
.NET(mono ランタイム) が管理するオブジェクトのメモリ測定には、
を使用します。これは Visual Studio と連携するアプリで、IDE から Run
Start Profiling とすると起動できるものです。
Java(Dalvik) が管理するオブジェクトのメモリ測定には、
を使用します。こちらは Android Studio をインストールすれば一緒に入っています。
Xamarin Android で、画面に2つのボタンを配置し、それぞれ次のような処理を行うコードを書きます。
[Activity(Label = "LeakSample", MainLauncher = true, Icon = "@mipmap/icon")]
public class MainActivity : Activity
{
System.IO.MemoryStream netStream = new System.IO.MemoryStream();
Java.IO.ByteArrayOutputStream javaStream = new Java.IO.ByteArrayOutputStream();
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
FindViewById<Button>(Resource.Id.myButton1).Click += (_, __) =>
{
var size = 10 * 1024 * 1024;
netStream.Write(new byte[size], 0, size);
};
FindViewById<Button>(Resource.Id.myButton2).Click += (_, __) =>
{
var size = 10 * 1024 * 1024;
javaStream.Write(new byte[size]);
};
}
}
myButton1
を押したときには、 .NET のクラスである System.IO.MemoryStream
にデータ追加します。
myButton2
を押したときには、 Java のクラスである Java.IO.ByteArrayOutputStream
にデータ追加します。
こんなプログラムを Run > Start Profiling で起動してみます。 アプリが起動する前に Xamarin Profiler が起動します。Choose target は既に起動したい Android アプリが設定されているので、「割り当て」を選択して「Next」します。
次の画面の「Enable automatic snapshots」をチェックすると自動的(一定間隔で)にメモリのスナップショットを記録しますがこれはお好みで。
「プリファイリングの開始」を押すとアプリが起動します。 Xamarin Profiler の上部にある カメラアイコン を押すと任意のタイミングでメモリ状態を記録できます。
myButton1
を数回押してから カメラアイコン を押してみましょう。
上図のように、追加した byte データが記録されています。
次に、myButton2
を数回押してから カメラアイコン を押してみましょう。
今度は Dalvik 管轄のオブジェクトへデータを追加したので Xamarin Profiler ではそのクラスは観測できません。(ワーキングセットは増えてるのでそれは観測できる?)
Dalvik が管理している領域のプロファイリングは Android Profiler を使います。 Xamarin であっても「それは Android/Java API をラップしただけ」の実体はネイティブ Android アプリなので、Android SDK のツールは使えるのです。
Android Studio を起動して適当な Android Apps のプロジェクトを開くか作ります(これはダミーです)。 次に メニュー > View > Tool Windows > Profiler で下部に Profiler ペインが開きます。 SESSIONS の横の「+」を押して、対象の端末 > Other processes > 対象のアプリID を選択すると、プロファイリングが始まります。
この状態で、アプリの myButton2
を何度か押すと、下図のようになります。
ボタンを押すたびにメモリ使用量が増えているのが確認できます。
(実は myButton1
を押すと、最初の1回はメモリ使用量が増えます。".NET だけ" には留まらないなにか、があるのでしょうか、おそらく。)
このように Xamarin(.NET)側のプロファイリングには Xamarin Profiler が、Java/Android API使用部のプロファイリングには Android Profiler がそれぞれ使用でき、同時利用あるいは併用することで、 Xamarin Android アプリの計測ができます。
これは Xamarin.Forms アプリでも同様です。その場合、Custom Renderer やライブラリの Android 依存な箇所の計測は Android Profiler に頼ることがでてくるでしょう。
また、Xamarin Profiler は Xamarin.iOS アプリの計測もできます。というか Xamarin Profiler の Look&Feel は Xcode - Instruments にとても似ていますね。
各種プロファイラ自体の使い方や機能については、私も全然把握できてないので、知見が溜まったらまた何か書きます。