Simpleperf

Simpleperf は NDK パッケージに含まれる多目的のコマンドライン ツールです。これを使用して、Android アプリケーション プロセスの CPU プロファイリングを実行できます。 このツールでは、Java、C/C++、Kotlin で記述されたアプリのホットスポット(つまり、アプリ内で最も実行時間の長いネイティブ コードの部分)を見つけることができます。 ホットスポットに関連するイベントは多くの場合、パフォーマンスの問題を示すため、アプリのパフォーマンスが重要な場合は、ホットスポットの原因を調査して修正する必要があります。

Simpleperf は Linux、Mac、または Windows で実行できます。 simpleperf ツールは NDK の ndk-location/simpleperf/ ディレクトリにあります。または、AOSP から アーリーアクセス事前ビルドをダウンロードできます。

要件

Simpleperf を使用するには、以下の要件を満たしている必要があります。

  • Android 5.0 (API レベル 21)以降を実行している端末を使用して、アプリをプロファイリングする。
  • 端末を USB デバッグ接続で開発マシンに接続する。
  • Python スクリプトを実行して記録および報告するには(推奨)、開発マシンに以下のものをインストールする。

    • Python 2.7 以降。
    • Android SDK および NDK の最新バージョン。 これらは Android Studio の SDK Manager を介してインストールできます。

使用方法

最新の使用方法については、Simpleperf の README をご覧ください。

クイックスタート

このセクションでは、Simpleperf を使用して Android アプリをプロファイリングする基本の手順について説明します。

1. プロファイリングするアプリの準備

プロファイリングするアプリはデバッグ可能でなければなりません。 アプリ マニフェストの <application> 要素で、android:debuggable 属性が true に設定されていることを確認します。 Android Studio で新しいモジュールを作成している場合は設定済みです。

Java または C++ コードのどちらのアプリをプロファイリングしているかに応じて、次のような追加の手順が必要になる場合があります。

  • Java コードをプロファイリングしており、Android O を実行している端末を使用している場合、wrap.sh ファイルを APK に追加する必要があります。 wrap.sh を APK にパッケージ化する方法については、Java コードのサンプル Gradle ビルド スクリプトをご覧ください。
  • C++ コードまたは事前にコンパイルされたネイティブ ライブラリのあるアプリをプロファイリングする場合は、次の点に注意してください。

Unity でビルドされた Android アプリを Simpleperf でプロファイリングするには、こちらの手順 を使用してデバッグ可能なシンボルを含めます。

2. アプリのプロファイリング セッションの設定

Simpleperf には、プロファイリング セッションを簡単に実行できるようにする Python スクリプト(app_profiler.py)が用意されています。 スクリプトの動作を設定するには、開発マシンの ndk-location/simpleperf/ ディレクトリにある app_profiler.config ファイルのプロパティを変更します。

主なプロパティを次の表に示します。

プロパティ名 説明
app_package_name プロファイリングするアプリのパッケージ名。 app_package_name="com.example.simpleperf.simpleperfexamplewithnative"
apk_file_path アプリをプロファイリングする開発マシン上にある、デバッグ可能な APK のパス。 apk_file_path = "../SimpleperfExampleWithNative/app/build/outputs/apk/app-profiling.apk"
android_studio_project_dir 開発マシン上にある、Android Studio プロジェクトのパス。 android_studio_project_dir = "../SimpleperfExampleWithNative/"
launch_activity プロファイリングするアプリの主なアクティビティ。 launch_activity = ".GameMainActivity"
recompile_app Dalvik バイトコードをデバッグ情報とともにネイティブ バイナリにコンパイルします。 Java のみのコードをプロファイリングする場合は、True に設定します。 それ以外の場合は False に設定します。 recompile_app = False
record_options 端末上で実行する「simpleperf record」コマンドに引数として渡すプロファイリング オプション。 record_options = "-g --duration 10"

プロファイリング セッションのコールグラフ情報を記録する必要がある場合は、記録オプションの設定方法について、記録の考慮事項 をご覧ください。

3. アプリ プロファイラの実行

開発マシンからプロファイリング セッションを開始するには、コマンドラインから app_profiler.py スクリプトを実行します。 スクリプトは ndk-location/simpleperf/ ディレクトリにあります。

$ python app_profiler.py

このスクリプトは次のアクションを実行します。

  • Android 端末のアーキテクチャに基づき、Simpleperf 実行可能ファイルのコピーを端末にプッシュします(たとえば、ターゲット端末が ARM64 に基づいている場合、スクリプトは ndk-location/simpleperf/bin/android/arm64/simpleperf 実行可能ファイルをその端末にコピーします)。
  • 端末上で「simpleperf record」コマンドを実行します。 成功した場合、このコマンドは収集したプロファイル情報で perf.data ファイルを生成します。
  • 生成された perf.data ファイルのコピーを開発マシンに送信して戻します。 デフォルトでは、ファイルは ndk-location/simpleperf/ ディレクトリに保存されます。 出力場所を変更するには、app_profiler.config ファイルの perf_data_path プロパティを変更します。

4. プロファイリング レポートの生成

プロファイリング レポートは、テキストモードまたはインタラクティブなグラフィック ユーザー インターフェースで表示できます。

  • テキストモード:ホスト プラットフォームで Simpleperf 実行可能ファイルを使用して「simpleperf report」コマンドを実行します。 たとえば、開発マシンで Linux を実行している場合は、ndk-location/simpleperf/bin/linux/x86_64/simpleperf を使用して report コマンドを実行します。
  • グラフィック モード:コマンドラインから report.py スクリプトを実行します。 このスクリプトは ndk-location/simpleperf/ ディレクトリにあります。 このスクリプトも、「simpleperf report」コマンドと同じ引数を受け入れます。

Simpleperf のヒントと手法

Simpleperf を使い始めたばかりのユーザーに特に役立つコマンドを紹介します。 その他のコマンドとオプションについては、Simpleperf コマンド リファレンスをご覧ください。

最も実行時間の長い共有ライブラリを検出する

このコマンドを実行すると、(CPU サイクル数に基づいて)実行時間に占める割合が最も大きい .so ファイルを確認できます。 このコマンドは、パフォーマンス分析セッションの開始時に最初に実行することをお勧めします。

$ simpleperf report --sort dso

最も実行時間の長い関数を検出する

最も実行時間の長い共有ライブラリを特定したら、このコマンドを実行して、その .so ファイルでの関数の実行にかかる時間の割合を確認します。

$ simpleperf report --dsos library.so --sort symbol

各スレッドでの実行時間の割合を確認する

.so ファイルでの実行時間は、複数のスレッドに分割できます。 このコマンドを実行すると、各スレッドでの実行時間の割合を確認できます。

$ simpleperf report --sort tid,comm

各オブジェクト モジュールでの実行時間の割合を確認する

実行時間の大部分を占めるスレッドが見つかったら、このコマンドを使用して、それらのスレッドでの実行時間が最も長いオブジェクト モジュールを特定できます。

$ simpleperf report --tids threadID --sort dso

関数呼び出しの関係を確認する

コールグラフは、プロファイリング セッション中に Simpleperf が記録するスタック トレースの視覚的な表現です。 コールグラフ情報の記録を開始する前に、記録の考慮事項 をご覧ください。

report -g コマンドを使用すると、どの関数が他の関数から呼び出されたかを示すコールグラフを出力できます。 これは、その関数自体の動作が遅くなっているのか、またはそれを呼び出している関数が原因で遅くなっているのかを判断するのに役立ちます。

$ simpleperf report -g

また、Python スクリプト report.py -g を使用して関数を表示するインタラクティブなツールを起動することもできます。 各関数をクリックすると、その子での処理にかかった時間を確認できます。

記録の考慮事項

Simpleperf には、プロファイリング セッション中にコールグラフ情報を記録する 2 つの基本的な方法があります。これは、DWARF ベースの方法(record --call-graph dwarf または record -g)とスタック フレーム ポインタ ベースの方法(record --call-graph fp)です。

一般に、--call-graph fp を使用して記録する方が --call-graph dwarf を使用する場合よりはるかに高速です。 AArch-64 アーキテクチャ(arm64-v8a)に基づいて構築された端末をプロファイリングする場合は、--call-graph fp オプションの使用をお勧めしますが、ARM アーキテクチャ (armeabiarmeabi-v7a)に基づく端末には使用できません。 これは、ARM アーキテクチャに基づいて構築された端末には通常、--call-graph fp オプションによる信頼性の高いスタックのアンワインドをサポートするスタック フレーム レジスタがないためです。

ARM アーキテクチャに基づいて構築された端末をプロファイリングする場合は、代わりに --call-graph dwarf オプションの使用を検討してください。 --call-graph dwarf オプションを使用すると、libunwind ライブラリを使用した Simpleperf でのスタックのアンワインドが可能になります。 --call-graph dwarf オプションを使用するには、ネイティブ ライブラリにデバッグ情報を提供する必要があります。 このため、何も削除されていないネイティブ ライブラリを含めるように APK をビルドすることをお勧めします。

Unity を使用してビルドしたアプリのプロファイリング

Unity を使用してビルドしたアプリをプロファイリングする場合は、次の手順に従ってデバッグ可能なシンボルを含めるようアプリをビルドしてください。

  1. Unity エディタで Android プロジェクトを開きます。
  2. Android プラットフォームの [Build Settings] ウィンドウで、[Development Build] オプションがオンになっていることを確認します。
  3. [Player Settings] をクリックして [Stripping Level] プロパティを [Disabled] に設定します。

問題の報告

問題を報告、または機能をリクエストするには、GitHub のandroid-ndk/ndk Issue Tracker を使用します。

関連ドキュメント

  1. Simpleperf コマンド リファレンス