Android モニターにはメモリーモニターが搭載されているので、 より簡単にアプリのパフォーマンスとメモリ使用状況を監視できます。 それにより、未割り当てオブジェクトを見つけ、メモリーリークを検知し、接続された端末が使用しているメモリ量を追跡します。 メモリーモニターはあなたのアプリがどのようにしてメモリを割り当てているかを報告し、アプリが使用しているメモリの可視化を手助けします。 そのおかげで、あなたは以下のことができるようになります:
メモリの使用をプロファイルして最適化するための典型的な作業の流れは、アプリを実行して以下を行うことです:
Java ヒープデータは、アプリケーションが割り当てたオブジェクトのタイプ、数、ヒープ上でのそれらのサイズをリアルタイムで表示します。 ヒープを見ると以下のことで役立ちます:
割り当てトラッキングでは、アプリのメモリー割り当てを記録し、コールスタック・サイズ・割り当てコードを含むプロファイルサイクルの全ての割り当てを一覧表示します。 これは以下のことで役立ちます:
Java ヒープをダンプ出力した時、メモリーモニターはAndroid固有のHeap/CPU Profiling (HPROF) ファイルを作成します。
これはHPROF ビューア上で閲覧できます。
HPROF ビューアではガベージコレクションルートは アイコン(と0の深度)を付けて表示し、
支配ノードは
アイコンを付けて表示します。
Javaにはいくつかの種類のガベージコレクションルートがあります。:
HPROF ファイルはルートの一覧を HPROF ビューアへ提供します。
支配ノードのツリーは、アプリによって作成されたオブジェクトへのパスをトレースします。 あるオブジェクトを通って直接的にもしくは間接的に他のオブジェクトへ到達することができる場合、そのオブジェクトは到達先オブジェクトを支配する支配ノードです。 メモリ使用の最適化をするためにアプリによって作成されたオブジェクトやパスを調べる際には、不要になったオブジェクトは削除してみてください。 支配ノードを解放するとその全ての下位ノードを解放できます。例えば以下の図でオブジェクトBを削除した場合、Bが支配しているオブジェクトC, D, E, Fが使用しているメモリーも解放されます。 実際のところは、オブジェクト C, D, E, Fが削除対象としてマークされていてもオブジェクト Bがまだそれらを参照していた場合は、 それが理由でオブジェクト C, D, E, Fが解放されない可能性があります。
アプリがメモリを効率的に使用して不要になったメモリを解放する場合、パフォーマンスは良くなります。 大きなメモリリークや時間と共に増大するメモリリークを修正することが最も重要です。
メモリ使用量の最適化を行うための方法の一つは、大きな配列型を分析することです。 例えば、配列内の個別要素のサイズを減らしてメモリーを節約することなんてできますか?
もう一つの注目すべき観点は、アプリでもう必要ないのに参照を続けているオブジェクトです。 異なる期間のヒープダンプを収集し、それらを比較してメモリリークが増大しているかどうか(コード上で複数回作成したが破棄していないオブジェクトなど)を判別します。 これらのオブジェクトは、例えば、動的に増える配列やオブジェクトツリーの一部の可能性があります。 この問題を洗い出すには、ヒープダンプを比較して、時間経過と共にインスタンスが増え続ける特定のオブジェクト型がないかを調べます。
ルートオブジェクトや支配ノードオブジェクトを含んだオブジェクトツリーが増大し続けると、下位のオブジェクトがガーベージコレクトされないことがあります。 この問題は、メモリリークやメモリ不足やクラッシュの一般的な原因となります。 アプリでは少数のオブジェクトによって多数の下位オブジェクトが破棄されるのを妨げていることがあり、その場合はすぐにメモリが不足してしまいます。 これらの問題を見つけるには、ヒープダンプを取得して、ルートオブジェクトや支配ノードオブジェクトによって保持されているメモリ量を調査します。 メモリが十分ある場合は、メモリ使用の最適化を開始する良い機会です。
メモリ問題の絞込みを始める際には、割り当てトラッカーも使ってメモリを食っているオブジェクトが割り当てられている場所をさらに把握する必要があります。 割り当てトラッカーは特定のメモリ使用を調べるだけでなく、読み込みやスクロールのような重要なコードパスを分析するのにも役立ちます。 For example, tracking allocations when flinging a list in your app allows you to see all of the allocations that need to be done for that behavior, what thread they are on, and where they came from. この情報は、これらのパスを絞り込んでアプリで必要な作業を減らし、UIの全体的な滑らかさ向上させるために非常に有用です。
不要な割り当てをするアルゴリズムや、同じオブジェクトを再利用せずに何度も作成する割り当てるアルゴリズムを調べるのが有効です。 例えば、あなたは一時的に使うオブジェクトや変数を再帰ループ内で毎回作成していませんか? 作成している場合、ループ内で使うオブジェクトや変数をループ前に作成しておくようにしてみてください。 さもないと、アプリでは再帰回数に応じて多くのオブジェクトと変数に不要な割り当てを行ってしまうかもしれません。
最大数かつ最大サイズのオブジェクトを作成するコード部分では、割り当てテストを行うことが重要です。 そういった場所は最適化する余地が最も多いのです。 ユニットテストに加えて、本物に近いデータを読み込んで(特にこれらデータ駆動型のアルゴリズムで)アプリをテストする必要があります。 また、アプリのキャシュ処理と起動フェイズを考慮するようにしてください。これらは場合によっては遅延を引き起こすからです ;正確な結果を得るには、これらのフェイズの後に割り当て分析を行うのがベストです。
コードを最適化したら、それが動作するかテストするようにしてください。 異なる負荷状況下で、メモリモニターツールは起動せずにテストをする必要があります。 最適化前と後の結果を比較して、パフォーマンスが実際に向上していることを確認してください。
Android モニターは端末やエミュレーターが使用している仮想マシン (VM) を使います:
VM はガベージコレクションを制御しています。Dalvik VM はガベージコレクションにマーク・アンド・スイープ方式を使用します。 ART VM は、世代別ガベージコレクションとマーク・アンド・スイープを組み合わせて使用し、メモリの断片化がひどくなった時などメモリが必要な場合により大きなガベージコレクションを行います。 logcat モニターは、発生したガベージコレクションの種類とその理由を示すいくつかのメッセージを表示します。
メモリーモニターの結果は、VMごとに異なる場合があります。 結果として、あなたが両方のVMをサポートしている場合は両方でテストを行うと良いでしょう。 さらに、異なるAPI levelで使用できるVMは、API levelごとに異なる動作をする場合があります。 例えば、 Android 2.3 (API level 10)以下でのDalvik VMは外部に割り当てられたメモリを使用し、Android 2.4以上ではDalvikヒープ内のみで割り当てをします。
Dalvik VMと ART VMを再設定してパフォーマンスを調整することはできません。 その代わりに、アプリのコードを調べてその処理をどのように改善させるかを決める必要があります(例えば、非常に大きな配列のサイズを減らす、など)。
ベストプラクティスではありませんが、VMがガベージコレクションを実行するタイミングをプログラム上から操作する方法もあります。 これらの技術はVM固有のものです。詳細については ガベージ コレクション(GC)の問題への対応 と RAM使用状況を調査するを参照してください。
ART VM では、Dalvik VMに比べてパフォーマンス・開発・デバッグにおける改善点がいくつか追加されています。 詳細については ART と Dalvikを参照してください。
特定の端末やエミュレーター上で動作しているアプリをメモリーモニターに表示するには:
グラフにて、y軸は空きRAMと割り当て済みRAMをメガバイト単位で表示しています。 x軸は時間の経過を示しています。; 最初は○秒で始まり、その後○分○秒と進んで行くといった具合です。 空きメモリの量(メガバイト単位で計測)は明るい色で表示され、割り当て済みメモリは暗い色になります。 割り当て済みメモリの数値が一気に下がったタイミングは、ガベージコレクションイベントが発生したことを示しています。
ガベージコレクションを強制実行するには、 Initiate GC をクリックします。
以下の図では、VM が最初のガベージコレクションを開始し、開発者が二つ目のガベージコレクションを強制的に実行しています。
このグラフを使えば潜在的な問題を把握できます:
例えば、以下のような問題の兆候が表示されることがあります:
ガベージコレクションは負荷が高いため、通常 VMは絶対に必要な時のみにガベージコレクションを実行します。 しかし、特定の状況ではガベージコレクションを強制的に実行できると便利です。 例えばメモリリークを検出する際、大きいオブジェクトの解放が正常に完了したかどうかを判別したい場合、いつもより多くガベージコレクションを実行することができます。
ガベージコレクションイベントを強制実行するには:
メモリモニターが動作したり停止したりしている間、スナップショットを取得することができます。 :