Experiments Never Fail

Xamarin Profiler と Android Profiler を併用して Xamarin Android アプリのメモリ使用量を測定する

Xamarin 製アプリのメモリのプロファイリングは、

を意識する必要があります。

使用するツール #

.NET(mono ランタイム) が管理するオブジェクトのメモリ測定には、

を使用します。これは Visual Studio と連携するアプリで、IDE から Run

Start Profiling とすると起動できるものです。

Java(Dalvik) が管理するオブジェクトのメモリ測定には、

を使用します。こちらは Android Studio をインストールすれば一緒に入っています。

試してみた #

Xamarin Profiler #

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 を数回押してから カメラアイコン を押してみましょう。

image.png

上図のように、追加した byte データが記録されています。

次に、myButton2 を数回押してから カメラアイコン を押してみましょう。

image.png

今度は Dalvik 管轄のオブジェクトへデータを追加したので Xamarin Profiler ではそのクラスは観測できません。(ワーキングセットは増えてるのでそれは観測できる?)

Android Profiler with Xamarin.Android apps #

Dalvik が管理している領域のプロファイリングは Android Profiler を使います。
Xamarin であっても「それは Android/Java API をラップしただけ」の実体はネイティブ Android アプリなので、Android SDK のツールは使えるのです。

Android Studio を起動して適当な Android Apps のプロジェクトを開くか作ります(これはダミーです)。
次に メニュー > View > Tool Windows > Profiler で下部に Profiler ペインが開きます。
SESSIONS の横の「+」を押して、対象の端末 > Other processes > 対象のアプリID を選択すると、プロファイリングが始まります。

この状態で、アプリの myButton2 を何度か押すと、下図のようになります。

image.png

ボタンを押すたびにメモリ使用量が増えているのが確認できます。
(実は 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 にとても似ていますね。

各種プロファイラ自体の使い方や機能については、私も全然把握できてないので、知見が溜まったらまた何か書きます。

published at tags: Android .NET Xamarin