lightbulb_outline Help shape the future of the Google Play Console, Android Studio, and Firebase. Start survey

CPU Profiler を使用して CPU Activity とメソッド トレースを検査する

CPU Profiler を使用すると、アプリの CPU 使用率とスレッド activity をリアルタイムで検査して、メソッド トレースを記録できるため、アプリのコードの最適化とデバッグが簡単になります。

CPU Profiler を開くには、次の手順を実行します。

  1. [View] > [Tool Windows] > [Android Profiler] をクリックします(ツールバーの [Android Profiler] をクリックすることもできます)。
  2. Android Profiler のツールバーからプロファイリングする端末とアプリプロセスを選択します。 USB 経由で端末に接続しているが、端末がリストに表示されない場合は、USB デバッグを有効にしていることを確認します。
  3. CPU タイムラインの任意の場所をクリックして CPU Profiler を開きます。

CPU 使用率をプロファイリングする必要がある理由

アプリの CPU 使用率を最小限にすると、より高速でスムーズなユーザー エクスペリエンスの実現や端末の電池寿命の維持など、多くのメリットがもたらされます。 また、さまざまな新旧の端末でアプリが適切に動作するようになります。 CPU Profiler を使うと、アプリを使用しているときに CPU 使用率やスレッド activity を監視することができます。 ただし、アプリがどのようにコードを実行しているかの詳細情報については、メソッド トレースを記録して検査する必要があります。

アプリプロセスの各スレッドで、一定の期間に実行されたメソッドや各メソッドがその実行中に消費した CPU リソースを確認できます。 また、メソッド トレースを使用して、呼び出し元呼び出し先を特定できます。 呼び出し元は別のメソッドを呼び出すメソッドであり、呼び出し先は別のメソッドによって呼び出されるメソッドです。 この情報を使用して、リソースを大量に消費する特定のタスクを頻繁に呼び出す原因になっているメソッドを特定し、アプリのコードを最適化して不要な動作を回避することができます。

ネイティブ システム プロセスの検査や、欠落したフレームに起因するぎこちない UI への対応に役立つ詳細なシステムレベル データを収集する場合は、systrace を使用する必要があります。

また、Debug クラスを使用して取得した .trace ファイルをエクスポートする場合は、Traceview を使用する必要があります。

CPU Profiler の概要

CPU Profiler を開くと、アプリの CPU 使用率とスレッド activity の表示が即座に開始されます。 すると、図 1 のような画面が表示されます。

図 1 CPU Profiler

図 1 に示すように、CPU Profiler のデフォルト ビューには次の項目が含まれます。

  1. イベント タイムライン: ライフサイクルでさまざまな状態に遷移するアプリの activity と、画面の回転イベントなどのユーザーによる端末操作を示します。 イベント タイムラインを有効にする方法など、イベント タイムラインの詳細については、 詳細なプロファイリングを有効にするをご覧ください。
  2. CPU タイムライン: アプリのリアルタイム CPU 使用率を利用可能な合計 CPU 時間の割合で表すとともに、アプリが使用しているスレッドの合計数を示します。 このタイムラインには、他のプロセス(システム プロセスまたは他のアプリ)の CPU 使用率も示されるため、アプリの CPU 使用率と比較することができます。 マウスをタイムラインの水平方向に動かして、CPU 使用率の履歴データを調べることができます。
  3. スレッド activity タイムライン: アプリ プロセスに属する各スレッドを一覧表示し、以下の色を使用して、スレッドの activity をタイムラインに沿って示します。 メソッド トレースを記録した後、このタイムラインからスレッドを選択して、トレースペインでそのデータを検査することができます。
    • 緑: スレッドがアクティブであるか、CPU を使う用意ができています。 つまり、スレッドが「実行」または「実行可能」状態です。
    • 黄: スレッドはアクティブですが、タスクを完了する前に、ディスク I/O やネットワーク I/O などの I/O 操作を待機しています。
    • グレー: スレッドがスリープ状態であり、CPU 時間を消費していません。 この状態は、スレッドがまだ利用できないリソースへのアクセスを要求したときに発生する場合があります。 スレッドは自発的にスリープ状態になるか、要求したリソースが利用可能になるまで、カーネルによってスリープ状態に置かれます。
  4. 記録構成: 以下のいずれかのオプションを選択して、プロファイラがメソッド トレースを記録する方法を決定します。
    • Sampled: アプリの実行中にアプリのコールスタックを高頻度で取得するデフォルトの構成です。 プロファイラは取得したデータセットを比較し、アプリのコード実行に関するタイミングとリソース使用量情報を導き出します。 サンプリング ベースのトレースに固有の問題は、コールスタックの取得後にアプリでメソッドが開始され、次のコールスタックの取得前にそのメソッドが終了した場合、そのメソッド呼び出しはプロファイラのログに記録されないことです。 このようなライフサイクルの短いメソッドを追跡する場合は、インストルメント化されたトレースを使用する必要があります。
    • Instrumented: アプリを実行時にインストルメント化して、各メソッド呼び出しの最初と最後にタイムスタンプを記録するデフォルトの構成です。 タイミング情報や CPU 使用率などのメソッド トレース データを生成するために、タイムスタンプが収集および比較されます。 各メソッドのインストルメント化に伴うオーバーヘッドにより、実行時パフォーマンスが低下し、プロファイリング データに影響が及ぶ場合があることに注意してください。これは、ライフサイクルが比較的短いメソッドの場合に顕著です。 また、アプリが短時間に多くのメソッドを実行すると、プロファイラ自身のファイルサイズの制限をすぐに超えて、以降のトレースデータを記録できなくなる場合があります。
    • Edit configurations: 上記のサンプリング ベースおよびインストルメント化された記録構成の特定のデフォルト動作を変更して、カスタム構成として保存できます。 詳細については、記録構成の作成のセクションをご覧ください。
  5. 記録ボタン: メソッド トレースの記録を開始および停止します。 詳細については、メソッド トレースの記録と検査のセクションをご覧ください。

注: プロファイラは、JDWPProfile SaverStudio:VMStatsStudio:PerfaStudio:Heartbeat(スレッド activity タイムラインに表示される正確な名前は異なる場合があります)など、Android Studio と Android プラットフォームがアプリプロセスに追加したスレッドの CPU 使用率もレポートします。 つまり、CPU タイムラインにあるアプリの CPU 使用率は、これらのスレッドが使用した CPU 時間も報告します。 これらのスレッドの一部をスレッド activity タイムラインで確認して、その activity を監視することができます (ただし、プロファイラ スレッドはネイティブ コードを実行するため、これらのスレッドのメソッド トレース データを記録することはできません)。Android Studio ではこのデータがレポートされるため、アプリのコードによってスレッド activity と CPU 使用率が実際に発生したタイミングを簡単に特定できます。

メソッド トレースの記録と検査

メソッド トレースの記録を開始するには、プルダウン メニューから、[Sampled] または [Instrumented] 記録構成を選択するか、作成したカスタム記録構成を選択し、[Record] をクリックします。 アプリを操作して、操作が完了したら、[Stop recording] をクリックします。 図 2 のように、プロファイラは、記録されたタイムフレームを自動的に選択し、メソッド トレース ペインにトレース情報を表示します。別のスレッドのメソッド トレースを検査する場合は、スレッド activity タイムラインからそのスレッドを選択します。

図 2 メソッド トレースを記録した後の CPU Profiler

  1. 選択されたタイムフレーム: トレースペインで検査する記録済みのタイムフレーム部分を示します。 メソッド トレースを初めて記録すると、CPU Profiler は、CPU タイムラインの記録全体を自動的に選択します。 記録されたタイムフレームの一部のみのメソッド トレース データを検査する場合は、ハイライト表示された領域の縁をクリックしてドラッグし、その長さを変更します。
  2. タイムスタンプ: 記録されたメソッド トレースの開始時間と終了時間(プロファイラが端末から CPU 使用状況情報の収集を開始したタイミングを基準にした時間)を示します。 タイムスタンプをクリックすると、選択したタイムフレームとして記録全体を自動的に選択できます。この操作は、複数の記録を切り替える必要がある場合に特に便利です。
  3. トレースペイン: 選択したタイムフレームとスレッドのメソッド トレース データを表示します。 このペインは、少なくとも 1 つのメソッド トレースを記録した後にのみ表示されます。 このペインで、各スタック トレースの表示方法を(トレースタブを使用して)選択したり、実行時間の計測方法を(タイム リファレンス プルダウン メニューを使用して)選択したりできます。
  4. メソッド トレースの表示方法([Top Down] ツリー、[Bottom Up] ツリー、 [Call Chart]、または [Flame Chart])を選択します。 各トレースペイン タブの詳細については、以下のセクションで説明します。
  5. プルダウン メニューから次のいずれかのオプションを選択して、各メソッド呼び出しのタイミング情報を計測する方法を決定します。
    • Wall clock time: タイミング情報が実際の経過時間を表します。
    • Thread time: タイミング情報として、実際の経過時間からスレッドが CPU リソースを消費していない時間を引いた時間を表します。 すべてのメソッドで、そのスレッド時間は常にウォール クロック時間以下になります。 スレッド時間を使用すると、特定のメソッドによるスレッドの実際の CPU 使用量について詳しく把握できます。

[Call Chart] タブを使用してトレースを検査する

[Call Chart] タブには、メソッド トレースがグラフィカル表示され、メソッド呼び出し(呼び出し元)の期間とタイミングが横軸に、その呼び出し先が縦軸に示されます。 システム API へのメソッド呼び出しはオレンジで、アプリのメソッドへの呼び出しは緑で、サードパーティの API(Java 言語 API を含む)へのメソッド呼び出しは青で示されます。 以下の図 3 は呼び出しチャートの例であり、セルフ時間、子時間、任意のメソッドの合計時間の概念を示しています。 これらの概念の詳細については、[Top Down] と [Bottom Up] を使用してトレースを検査する方法のセクションで説明します。

図 3 セルフ時間、子時間、メソッド D の合計時間を示した呼び出しチャートの例

ヒント: メソッドのソースコードにジャンプするには、メソッドを右クリックして、[Jump to Source] を選択します。 この操作は、すべてのトレースペイン タブで行えます。

[Flame Chart] タブを使用してトレースを検査する

[Flame Chart] タブには、反転された呼び出しチャートが表示され、同一のコールスタックが集約されます。 つまり、同じ順序の呼び出し元を共有する同一のメソッドが集められ、(呼び出しチャートのようにメソッドを複数の短いバーで表示せずに)フレーム チャートに 1 つの長いバーとして表されます。 これにより、最も多くの時間を消費しているメソッドを簡単に確認できるようになります。 ただし、この場合、横軸がタイムラインを表さなくなり、その代わり、各メソッドの実行にかかった相対的な時間が示されます。

この概念について、以下の 図 4 に示す呼び出しチャートを例に説明します。 メソッド D が B に対して複数の呼び出し(B1、B2、B3)を実行し、B へのこれらの呼び出しの一部が C に対して呼び出し(C1 と C3)を実行していることに注意してください。

図 4 共通の順序の呼び出し元を共有している複数のメソッド呼び出しが含まれた呼び出しチャート

B1、B2、B3 は同じ順序の呼び出し元(A → D → B)を共有しているため、以下のように集約されます。 同様に、同じ順序の呼び出し元(A → D → B → C)を共有している C1 と C3 も集約されます。C2 の呼び出し元の順序は異なるため((A → D → C)、集約に含まれないことに注意してください。

図 5 同じコールスタックを共有している同一のメソッドの集約

集約されたメソッド呼び出しは、図 6 のようなフレーム チャートの作成に使用されます。フレーム チャートのすべてのメソッド呼び出しで、最も多くの CPU 時間を消費する呼び出し先が最初に表示されることに注意してください。

図 6 図 4 の呼び出しチャートをフレーム チャートで表した図

[Top Down] と [Bottom Up] を使用してトレースを検査する

[Top Down] タブには、メソッド呼び出しのリストが表示され、メソッドノードを展開すると、その呼び出し先が表示されます。 図 7 は、図 3 の呼び出しチャートのトップダウン グラフを示しています。グラフの各矢印は呼び出し元から呼び出し先を指しています。

図 7 に示すように、[Top Down] タブでメソッド A のノードを展開すると、その呼び出し先であるメソッド B とメソッド D が表示されます。 さらに、メソッド D のノードを展開すると、その呼び出し先であるメソッド B とメソッド C が表示され、メソッド B でも同じように呼び出し先が表示されます。 [Flame Chart] タブの場合と同じように、トップダウン ツリーでは、同じコールスタックを共有している同一のメソッドのトレース情報が集約されます。 つまり、[Flame Chart] タブの表示は、[Top Down] タブのグラフィカル表示です。

[Top Down] タブには、各メソッド呼び出しで消費された CPU 時間を説明するために以下の情報が表示されます(時間は、選択したタイムフレーム内にあるスレッドの合計時間の割合としても表されます)。

  • Self: 図 3 のメソッド D が示しているように、メソッド呼び出しが自身のコードの実行に費やした時間であり、その呼び出し先の実行に費やした時間ではありません。
  • Children: 図 3 のメソッド D が示しているように、メソッド呼び出しがその呼び出し先の実行に費やした時間であり、自身のコードの実行に費やした時間ではありません。
  • Total: メソッドのセルフ時間と時間の合計です。 これは、図 3 のメソッド D が示しているように、アプリがメソッド呼び出しの実行に費やした合計時間を表します。

図 7 トップダウン ツリー

図 8 図 7 のメソッド C のボトムアップ ツリー

[Bottom Up] タブには、メソッド呼び出しのリストが表示され、メソッドのノードを展開すると、その呼び出し元が表示されます。 図 8 には、図 7 のトレース例に応じたメソッド C のボトムアップ ツリーが示されています。 ボトムアップ ツリーでメソッド C のノードを開くと、その一意の各呼び出し元であるメソッド B とメソッド D が表示されます。

メソッド B はメソッド C を 2 回呼び出しますが、ボトムアップ ツリーでメソッド C のノードを展開すると、メソッド B が 1 つだけ表示されることに注意してください。 さらに、メソッド B のノードを展開すると、その呼び出し元であるメソッド A とメソッド D が表示されます。

[Bottom Up] タブは、最も多くの(または最も少ない)CPU 時間を消費したスレッド順にスレッドを並べ替えるのに便利です。 また、各ノードを調べて、これらのメソッドを呼び出すときに最も多くの CPU 時間を消費した呼び出し元を特定することができます。 トップダウン ツリーとは異なり、ボトムアップ ツリーの各メソッドのタイミング情報は、各ツリーの最上部のメソッド(トップノード)に関連しています。

CPU 時間は、記録中のスレッドの合計時間の割合としても表されます。 次の表は、トップノードとその呼び出し元のメソッド(サブノード)のタイミング情報を解釈する方法を理解するのに役立ちます。

Self Children Total
ボトムアップ ツリーの最上位のメソッド(トップノード) メソッドが自身のコード(その呼び出し先ではない)の実行に費やした合計時間を表します。 トップダウン ツリーとは異なり、このタイミング情報は、記録中におけるこのメソッドへのすべての呼び出しの合計時間を表しています。 メソッドがその呼び出し先(自身のコードではない)の実行に費やした合計時間を表します。 トップダウン ツリーとは異なり、このタイミング情報は、記録中におけるこのメソッドの呼び出し先へのすべての呼び出しの合計時間を表しています。 セルフ時間と子時間の合計です。
呼び出し元のメソッド(サブノード) 呼び出し元から呼び出されたときの呼び出し先のセルフ時間の合計を表します。 図 8 のボトムアップ ツリーを例として説明すると、メソッド B のセルフ時間は、メソッド B から呼び出されるたびに実行されるメソッド C のセルフ時間の合計に等しくなります。 呼び出し元から呼び出されたときの呼び出し先の子時間の合計を表します。 図 8 のボトムアップ ツリーを例として説明すると、メソッド B の子時間は、メソッド B から呼び出されるたびに実行されるメソッド C の子時間の合計に等しくなります。 セルフ時間と子時間の合計です。

注: Android Studio は、特定の記録中にプロファイラがファイルサイズの制限に到達すると、新しいデータの収集を停止します(ただし、記録は停止しません)。 通常、インストルメント化されたトレースを実行すると、データの収集がより早く停止します。このタイプのトレースでは、サンプリング ベースのトレースよりも短い時間でより多くのデータを収集するからです。 インスペクション タイムフレームを、制限への到達後に発生した記録期間に拡張した場合、トレースペインのタイミング データは変化しません(新しいデータが利用できないため)。 また、データが利用できない記録の部分のみを選択すると、トレースペインには、タイミング情報として NaN が表示されます。

記録構成の作成

Android Studio が提供する [Sampled] や [Instrumented] などの記録構成を選択するか、独自の記録構成を作成します。 カスタム構成を作成または編集したり、既存のデフォルト構成を検査するには、記録構成のプルダウン メニューから [Edit configurations] を選択して、[CPU Recording Configurations] ダイアログを開きます。

図 9 [CPU Recording Configurations] ダイアログで、カスタム記録構成を作成または編集したり、既存のデフォルト構成を検査したりできます。

左のペインで既存の構成を選択して、その構成の設定を検査したり、次の手順を実行して、新しい記録構成を作成したりできます。

  1. ダイアログの左上にある [Add] をクリックします。 そうすると、いくつかのデフォルト設定が適用された新しい構成が作成されます。
  2. 構成に名前を付けます。
  3. [Trace Technology] セクションで [Sampled] または [Instrumented] を選択します。 これらの各オプションは、CPU Profiler の概要で説明したように機能します。
  4. サンプリング ベースの記録構成の場合は、[Sampling interval] をマイクロ秒単位(μs)で指定します。 この値は、アプリのコールスタックの各サンプル間の時間を表します。 指定する時間が短いほど、記録データのファイルサイズ制限により早く到達することに注意してください。
  5. 接続された端末に書き込まれる記録データの [File size limit] をメガバイト単位(MB)で指定します。 記録を停止すると、Android Studio はこのデータを解析し、プロファイラ ウィンドウに表示します。 したがって、ファイルサイズ制限を拡大して、大量のデータを記録すると、Android Studio ではファイルの解析により長い時間がかかり、応答しなくなる場合があります。

    注: API レベル 26 以降を実行している端末を接続している場合は、トレースデータのファイルサイズ制限はなく、この値を無視できます。ただし、各記録の後、端末が収集するデータの量には引き続き注意する必要があります。Android Studio では大きなトレース ファイルの解析が難しくなる場合があります。たとえば、短いサンプリング間隔でサンプリング ベースのトレースを記録しているか、またはアプリが短い間に多くのメソッドを呼び出すときにインストルメント化されたトレースを記録している場合は、大きなトレース ファイルが短時間で生成されます。

  6. [Apply] または [OK] をクリックします。 他の記録構成に変更を加えた場合は、それらの変更も適用されます。

新しい構成を作成すると、記録構成のプルダウン メニューからその構成が自動的に選択されるので、次の記録でその構成を使用できます。