Android
Xamarin

Xamarin.Android でメモリを大量に確保したら落ちた話

More than 3 years have passed since last update.

例えば、複数の画像を読み込んで加工して…みたいな処理を行うときに気をつけなきゃいけない話。

MainActivity.cs
[Activity(Label = "AllocTestDroid", MainLauncher = true)]
public class MainActivity : Activity
{
    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
        SetContentView(Resource.Layout.Main);

        FindViewById<Button>(Resource.Id.myButton).Click += (_, e) => 
        {
            using (var stream = new MemoryStream())
            {
                var size = 1024 * 1024 * 100; // 100Mbyte
                stream.Write(new byte[size], 0, size);
            }

            Console.WriteLine("GC.GetTotalMemory:" + GC.GetTotalMemory(true).ToString());
        };
    }
}

ボタンを押した時に、MemoryStream に 100Mbytes のデータを追加して、すぐ (using のスコープを抜けて) Dispose する処理なんですけども。

実機(初代HTC J)では、5回くらいボタンを押すと アプリが落ちました

GC.GetTotalMemory の結果は↓の通り。
Dispose してるから、メモリ使用量は増えないのかなーと思ったんですけど。ガベージコレクションについて全然詳しくないので分かってないです。
GC.Collect() とか Java.Lang.Runtime.GetRuntime().Gc() を呼んでみたけど変わらず。)

GC.GetTotalMemory:214005592
GC.GetTotalMemory:423742528
GC.GetTotalMemory:633457864
GC.GetTotalMemory:843173096

10Mbytes の場合

size1024 * 1024 * 10 にして試すと、まったく落ちなくなりました。

GC.GetTotalMemory の結果も、

GC.GetTotalMemory:25202264
GC.GetTotalMemory:25283616
GC.GetTotalMemory:25283720
GC.GetTotalMemory:25283720
GC.GetTotalMemory:25283720
GC.GetTotalMemory:25283720
…

と安定しているようです。

モバイルで 100Mbytes も使う処理自体が異常だと思いますが、複数のタスクに分割してあげれば大丈夫なのかな、と。

追記 2014.03.13

@atsushieno さんより、

との情報を頂きました。(まだ試してない…)