ヒープサイズ (その2)

ログからはヒープの伸びも頭打ちもまだはっきりしないため、まだメモリリークがあるかどうか分からない。
もう少し大きなヒープで試したい所だ。

ということで大きなヒープで動かしてみよう。

iOSは私の知っている限りでは「アプリケーションヒープを制御する」という項目は見当たらない。VM方式をとっていないアプリケーションのため、そもそもアプリケーションヒープの上限は無くて、空きメモリ使えがなくなったらそこで終わりなのかもしれないがandroidに比べてすぐにOOMが発生するのではなく、メモリ不足の警告が出て、不要なメモリを空けて、それでもダメだと優先度の低いアプリケーションから落とされていくように見える。

androidはVMを使っていることもあり、VMが使用するアプリケーションのヒープをコントロールできる。androidはHoneycomb(3.0) からタブレットを始めとした規模の大きなアプリケーションのためにヒープの上限を256MBに引き上げたラージヒープをマニフェストで設定可能にしている。

ラージヒープはAndroidMenifest.xmlのapplication要素で行う。

    <application
       〜
        android:largeHeap="true">

機種によって変わる可能性があるが、リファレンス実装ではlargeHeap属性でアプリケーションヒープの上限を256MBに上げることができる。
ただし、エミュレータでは注意が必要だ。実際に試した所エミュレータはAVDの設定 VM Heapを上限として優先しているようで、この値を変えない限り、largeHeapの指定を行ってもヒープの上限が拡張されない。


さて、実際にlargeheapで実行してみよう。

: D/dalvikvm(1548): GC_FOR_ALLOC freed 11K, 1% free 37719K/37895K, paused 2ms, total 2ms
: I/dalvikvm-heap(1548): Grow heap (frag case) to 51.138MB for 14962300-byte allocation
: D/dalvikvm(1548): GC_CONCURRENT freed 1K, 1% free 52329K/52551K, paused 13ms+0ms, total 16ms
: D/dalvikvm(1548): GC_FOR_ALLOC freed 14683K, 29% free 37906K/52679K, paused 4ms, total 16ms
: I/dalvikvm-heap(1548): Grow heap (frag case) to 51.322MB for 14962300-byte allocation
: D/dalvikvm(1548): GC_CONCURRENT freed 21K, 1% free 52497K/52679K, paused 18ms+1ms, total 21ms
: D/dalvikvm(1548): GC_FOR_ALLOC freed 12092K, 24% free 40405K/52679K, paused 20ms, total 20ms
: I/dalvikvm-heap(1548): Grow heap (frag case) to 51.290MB for 12369932-byte allocation
: D/dalvikvm(1548): GC_CONCURRENT freed 0K, 1% free 52485K/52679K, paused 16ms+1ms, total 19ms
--------------------- 2値化→輪郭抽出 1回目ここまで------------------------------------
: D/dalvikvm(1548): GC_FOR_ALLOC freed 151K, 1% free 52345K/52679K, paused 3ms, total 3ms
: I/dalvikvm-heap(1548): Grow heap (frag case) to 65.422MB for 14962300-byte allocation
: D/dalvikvm(1548): GC_CONCURRENT freed <1K, 1% free 66956K/67335K, paused 24ms+0ms, total 27ms
: D/dalvikvm(1548): GC_FOR_ALLOC freed 14648K, 23% free 52414K/67335K, paused 4ms, total 26ms
: I/dalvikvm-heap(1548): Grow heap (frag case) to 65.490MB for 14962300-byte allocation
: D/dalvikvm(1548): GC_CONCURRENT freed 41K, 1% free 66985K/67335K, paused 18ms+1ms, total 21ms
: D/dalvikvm(1548): GC_FOR_ALLOC freed 26692K, 41% free 40293K/67335K, paused 4ms, total 4ms
: I/dalvikvm-heap(1548): Grow heap (frag case) to 51.180MB for 12369932-byte allocation
: D/dalvikvm(1548): GC_CONCURRENT freed <1K, 23% free 52373K/67335K, paused 18ms+1ms, total 21ms
:
:

と、処理を繰り返してもヒープの上限は65MB近辺で頭打ちになるようになった。
以降何度処理を繰り返しても70MBを超えてヒープが増加する様子は見られないため、現状のコードでは通常のアプリケーションヒープサイズ(64MB)では足りないぎりぎりのヒープが必要だという結論になりそうだ。

さて、ならばヒープをラージにすれば良いかというと中々難しい所だ。全ての端末で有効な指定ではないだろうし、設定してもシステム全体のメモリが足りない場合は当然割り当てられることは無いだろう。選択肢としては

  • LargeHeapを指定して、対応する端末を仕様 (ICS以降、256MBの空きメモリ)を限定する
  • LargeHeapは指定せず、扱える画像データのサイズに上限を設定する (1024x768までとか)

このどちらかだろうが、悩むところ。