日アンドロイドアプリのメモリ容量を取得する(前編)アンドロイドはLinuxカーネル(2.6.x-3.x)をベースにしたOSに、JavaVM(DalvikVM)を実装しており、複雑なメモリ管理を行っている。スマートフォンの限られたリソース環境の中で、アプリケーションが快適に動作するように設計されている。メモリが足りなくなるとアプリが突然終了したり、処理速度が遅くなるので、一般のユーザーもメモリがどれぐらい空いているかといったことに関心があるだろう。設定で実行中のアプリのメモリ利用量を見ることができるが、これは具体的にはどこの値を見てるのだろうか。スマートフォンのスペックから搭載されているメモリ容量はわかるが、実際利用できるメモリ量はどれぐらいだろうか。スマートフォンのメモリ容量は増え続けているが、UI/UXの向上やデザインリソースの増加にともなってアンドロイドアプリ自体の容量も増加傾向にある。アンドロイドのアプリケーションプログラマは、常にメモリ不足とパフォーマンス劣化に悩まされる。非同期処理を多用しなければならないので、プログラミングは複雑だ。省メモリかつパフォーマンスのよいアンドロイドアプリを開発するには、メモリ管理は、VMにまかせておけばいいというわけにもいかない。アプリケーションプログラマも、アンドロイドの深い知識を得る努力が必要である。自身のアプリのメモリ利用量や他のアプリのメモリ利用量を調べることで、アンドロイドのメモリ管理方法を理解する糸口としたい。アンドロイドが利用できるメモリ量アンドロイド端末のメモリ量は、どこを見ればわかるだろうか。スペック表のメモリ欄には、RAM/ROMのそれぞれの容量が書かれていることが多い。このRAMがメモリ量だと考えて良いだろう。ROMはEEPROMの一種で、不揮発かつ書き換え可能なNAND型フラッシュメモリである。これは主にストレージに利用される。プログラムやデータが保存されているのが、ROMで、プログラムが実行されるときにロードされるのが、RAMだとおおざっぱに解釈していいだろう。アンドロイド端末を持っていれば、設定のアプリケーションの管理で実行中のアプリを見れば、どこかにメモリ量を表す数値があるはずである。設定から見るメモリ量は明らかにスペックにある数字より小さいはずである。搭載しているメモリ全てが利用できるわけではない。設定のメモリ量たとえば、今私の手元にあるアンドロイド端末のスペックは、512M/2Gとなっている。最近では2G/32-64Gというものもあるので、今では少ないように感じる。このアンドロイド端末の設定で、メモリ容量を見ると利用が182MBで空きが65MBとなっており、合計247MBということになる。スペック上のサイズの半分以下である。この画面をみていると、空きも利用量も刻々と変化しており、都度合計値も変わっている。アプリが動作しているので、その間に利用量が変わったり、空きの量が変わるのはわかるが、合計が変わるのはなぜだろうか。正確な理由はわからないが、原因のひとつは刻々と変化することにあるのではないだろうか。メモリ量算出とは、そう単純な話ではなさそうだというのはわかる。他に全メモリ量を取得する方法がないか調査してみる。AndoridのAPIには以下のようなものがある。Level16以上のSDKを利用しなければならない。Android4.1で試したところ、/proc/meminfoのMemTotalと一致)。これは置いておいて、さらに違う方法で全メモリ容量を調べてみる。以下のadbコマンドを実行すると、メモリ情報が取得できる。kBmeminfoから512MBのうち、340MBは利用できることがわかる。これが全てアンドロイドアプリで利用できるわけではない。MemFreeは空き容量ということではなく、用途が決まっていない容量とでもいうべきものである。アンドロイドのmeminfoの特徴として、通常のLinuxのMemFreeの値と比べるとアンドロイドのものは、かなり小さい。file(file-backed:ファイルから読み直せばいいので、いつでも廃棄できる領域)領域よりanon(swapしなければ廃棄できない領域)領域が非常に大きい。これはデフォルトではswapが無効となっていることが影響しているのかもしれない(SwapTotalは0)。linuxカーネルのswapを有効にするアプリ(rooted)もあるので、機能自体は存在する。このアンドロイド端末の設定やAPIが、どのように算出しているのかわからないので、なんともいえないが、アンドロイドで利用できる全メモリ容量を取得するのも一筋縄でいかないことがわかるだろう。どの値がほんとの利用可能メモリ容量値なのかmeminfoの情報から、カーネル以外が利用できるメモリは、Active+InActiveの合計が近似値だろうと推測する。この場合、280MB程度ではないだろうか。Unvictableは破棄不可能という意味だが、これも加算すべきだろう。どちらにしろ、Kbyte単位の精度は難しいので、Mbyte単位ぐらいの精度を求めることを目標とする。kBmeminfoのMemTotalが340MBだから、60MBがカーネルの利用量とMemFreeということになるが、数字が合わない。カーネルの利用量をSlab,KernelStack,PageTables,VmallocUsedとすると、カーネルの利用量がかなり大きくなってしまうが、VmallocUsedはカーネル内のvmalloc()で確保されたもので、外部デバイスのIOメモリマッピングも含むため単純に全て加算できない。/proc/vmallocinfoの中から、vmallocの分だけ計算してみると、12MB程度なので、カーネルの利用量は56MBとなる。kB別のアプローチとして、動作しているアプリのメモリ利用量を合計して、空き容量を加算することで、全体容量値とすることも可能だろう。後編では、起動中のアンドロイドアプリのメモリ利用量を取得する方法の紹介と、そこから全体容量値を求めてみたい。