Macrobenchmark ライブラリは、アプリの起動や複雑な UI 操作(LazyColumn のスクロールやアニメーションの実行など)のようなアプリ内の比較的大きな領域に対応するユースケースをテストするために使用します。比較的小さな領域のコードをテストする場合は、Microbenchmark をご覧ください。このページでは、Macrobenchmark ライブラリの設定方法について説明します。
ライブラリは、Android Studio コンソールと JSON ファイルの両方に詳細情報付きのベンチマーク結果を出力します。Android Studio に読み込んで分析できるトレース ファイルも提供します。
継続的インテグレーションでベンチマークを実行するで説明しているように、継続的インテグレーション(CI)環境で Macrobenchmark ライブラリを使用します。
Macrobenchmark を使用してベースライン プロファイルを生成できます。最初に Macrobenchmark ライブラリを設定すると、ベースライン プロファイルを作成できます。
Jetpack Compose で作成された UI のテストには、Macrobenchmark が推奨されます。Compose ノードを操作する UI Automator テストを作成する方法については、相互運用性をご覧ください。
プロジェクトの設定
Macrobenchmark は、Android Studio の最新バージョンで使用することをおすすめします。
Macrobenchmark モジュールを設定する
Macrobenchmark では、アプリを測定するテストを実行するために、アプリコードとは別個の com.android.test モジュールが必要です。
Android Studio には、Macrobenchmark モジュールの設定を簡素化するテンプレートが用意されています。ベンチマーク モジュール テンプレートを使用すると、アプリ モジュールによってビルドされたアプリを測定するためのモジュール(サンプル起動ベンチマークなど)が、プロジェクト内に自動的に作成されます。
モジュール テンプレートを使用して新しいモジュールを作成する手順は次のとおりです。
Android Studio の [Project] パネルでプロジェクトまたはモジュールを右クリックして、[New] > [Module] を選択します。
[Templates] ペインで [Benchmark] を選択します。ターゲット アプリ(ベンチマーク対象のアプリ)に加えて、新しい Macrobenchmark モジュールのパッケージ名とモジュール名をカスタマイズできます。
[Finish] をクリックします。
アプリを設定する
アプリ(Macrobenchmark の「ターゲット」)のベンチマークを行うには、そのアプリを profileable にして、パフォーマンスを損なうことなく、詳細なトレース情報を読み取れるようにする必要があります。モジュール ウィザードを使用すると、アプリの AndroidManifest.xml ファイルに <profileable> タグが自動的に追加されます。
ターゲット アプリに ProfilerInstaller 1.3 以降が含まれていることを確認します。これは、Macrobenchmark ライブラリがプロファイルのキャプチャとリセット、およびシェーダー キャッシュの消去を有効にするために必要です。
できる限りリリース バージョン(製品版)に近くなるようにベンチマーク対象のアプリを構成します。
アプリはデバッグ不可として設定します。パフォーマンスを高めるために、圧縮をオンにすることをおすすめします。そのためには、通常、リリース バリアントのコピーを作成します。これは同じ処理を行いますが、デバッグキーを使用してローカルで署名されます。または、initWith を使用して Gradle に処理を指示することもできます。
Kotlin
buildTypes { getByName("release") { isMinifyEnabled = true isShrinkResources = true proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt")) } create("benchmark") { initWith(getByName("release")) signingConfig = signingConfigs.getByName("debug") } }
Groovy
buildTypes { release { isMinifyEnabled = true isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "keep-rules.pro" ) // In real app, this would use its own release keystore signingConfig = signingConfigs.getByName("debug") baselineProfile.automaticGenerationDuringBuild = true } }
図 2 に示すように、ベンチマークが実行されてアプリの正しいバリアントが作成およびテストされるようにするには、次の操作を行います。
- Gradle 同期を実行します。
- [Build Variants] パネルを開きます。
- アプリと Macrobenchmark モジュールの両方のベンチマーク バリアントを選択します。
(省略可)マルチモジュール アプリを設定する
アプリに複数の Gradle モジュールがある場合は、コンパイルするビルド バリアントをビルド スクリプトが認識できるようにします。:macrobenchmark モジュールと :app モジュールの benchmark ビルドタイプに matchingFallbacks プロパティを追加します。残りの Gradle モジュールについては、以前と同じ構成で問題ありません。
Kotlin
create("benchmark") { initWith(getByName("release")) signingConfig = signingConfigs.getByName("debug") matchingFallbacks += listOf("release") }
Groovy
benchmark { initWith buildTypes.release signingConfig signingConfigs.debug matchingFallbacks = ['release'] }
そうしないと、新しく追加された benchmark ビルドタイプが原因でビルドが失敗し、次のエラー メッセージが表示されます。
> Could not resolve project :shared.
Required by:
project :app
> No matching variant of project :shared was found.
...
プロジェクト内のビルド バリアントを選択する際は、:app と :macrobenchmark の各モジュールには benchmark を、アプリ内の他のモジュールには release を選択します。図 3 をご覧ください。
詳しくは、バリアント マッチングに関連するビルドエラーを解決するをご覧ください。
(省略可)プロダクト フレーバーを設定する
アプリに複数のプロダクト フレーバーを設定している場合は、:macrobenchmark モジュールを構成して、ビルドとベンチマークを行うアプリのプロダクト フレーバーをモジュールが認識できるようにします。
この例では、次のスニペットに示すように、:app モジュールで 2 つのプロダクト フレーバー(demo と production)を使用しています。
Kotlin
flavorDimensions += "environment" productFlavors { create("demo") { dimension = "environment" // ... } create("production") { dimension = "environment" // ... } }
Groovy
flavorDimensions 'environment' productFlavors { demo { dimension 'environment' // ... } production { dimension 'environment' // ... } }
この構成を行わないと、複数の Gradle モジュールがある場合と似たビルドエラーが発生する可能性があります。
Could not determine the dependencies of task ':macrobenchmark:connectedBenchmarkAndroidTest'.
> Could not determine the dependencies of null.
> Could not resolve all task dependencies for configuration ':macrobenchmark:benchmarkTestedApks'.
> Could not resolve project :app.
Required by:
project :macrobenchmark
> The consumer was configured to find a runtime of a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'benchmark', attribute 'com.android.build.api.attributes.AgpVersionAttr' with value '7.3.0'. However we cannot choose between the following variants of project :app:
- demoBenchmarkRuntimeElements
- productionBenchmarkRuntimeElements
All of them match the consumer attributes:
...
以下の 2 つのセクションでは、複数のプロダクト フレーバーでベンチマークを構成する方法について説明します。
MissingDimensionStrategy を使用する
:macrobenchmark モジュールの defaultConfig で missingDimensionStrategy を指定すると、ビルドシステムに対してフレーバー ディメンションにフォールバックするよう指示できます。モジュールにディメンションが見つからない場合は、使用するディメンションを指定します。次の例では、デフォルトのディメンションとして production フレーバーを使用しています。
Kotlin
defaultConfig { missingDimensionStrategy("environment", "production") }
Groovy
defaultConfig { missingDimensionStrategy "environment", "production" }
このように、:macrobenchmark モジュールは指定されたプロダクト フレーバーのビルドとベンチマークのみを行うことができます。これは、ベンチマーク対象の適切な構成を持つプロダクト フレーバーが 1 つのみであることがわかっている場合に便利です。
:macrobenchmark モジュールでプロダクト フレーバーを定義する
他のプロダクト フレーバーをビルドしてベンチマークを行う場合は、:macrobenchmark モジュールでそれらを定義します。指定方法は :app モジュールの場合と似ていますが、productFlavors を dimension に割り当てるだけです。その他の設定は必要ありません。
Kotlin
flavorDimensions += "environment" productFlavors { create("demo") { dimension = "environment" } create("production") { dimension = "environment" } }
Groovy
flavorDimensions 'environment' productFlavors { demo { dimension 'environment' } production { dimension 'environment' } }
プロジェクトを定義して同期したら、図 4 のように、[Build Variants] ペインから該当するビルド バリアントを選択します。
詳しくは、バリアント マッチングに関連するビルドエラーを解決するをご覧ください。
Macrobenchmark クラスを作成する
ベンチマーク テストは、Macrobenchmark ライブラリの MacrobenchmarkRule JUnit4 Rule API によって提供されます。この API には、ターゲット アプリを実行してベンチマークを行う方法についてさまざまな条件を指定できる measureRepeated メソッドが含まれています。
少なくとも、ターゲット アプリの packageName、測定する metrics、ベンチマークの実行対象である iterations の数を指定する必要があります。
Kotlin
@LargeTest @RunWith(AndroidJUnit4::class) class SampleStartupBenchmark { @get:Rule val benchmarkRule = MacrobenchmarkRule() @Test fun startup() = benchmarkRule.measureRepeated( packageName = TARGET_PACKAGE, metrics = listOf(StartupTimingMetric()), iterations = DEFAULT_ITERATIONS, ) { // starts default launch activity uiAutomator { startApp(TARGET_PACKAGE) } } }
ベンチマークをカスタマイズするすべてのオプションについては、ベンチマークをカスタマイズするセクションをご覧ください。
Compose UI のインタラクションをベンチマークする
前の例ではアプリの起動を測定しましたが、スクロール中のフレーム落ち(ジャンク)など、UI のパフォーマンスを測定することもよくあります。
Jetpack Compose アプリケーションのベンチマーク(LazyColumn のスクロール中の FrameTimingMetric の測定など)を行うには、次のスニペットに示すように、UI Automator を使用して Compose ノードと直接やり取りできます。
@LargeTest
@RunWith(AndroidJUnit4::class)
class ComposeScrollBenchmark {
@get:Rule
val benchmarkRule = MacrobenchmarkRule()
@Test
fun scrollLazyColumn() = benchmarkRule.measureRepeated(
packageName = "com.example.compose.app",
metrics = listOf(FrameTimingMetric()),
iterations = 5,
startupMode = StartupMode.WARM,
setupBlock = { pressHome() }
) {
startActivityAndWait()
// Find the Compose node using the testTag defined in your app
val lazyColumn = device.findObject(By.res("my_lazy_column"))
// Simulate a scroll gesture to measure FrameTimingMetric
lazyColumn.setGestureMargin(device.displayWidth / 5)
lazyColumn.fling(Direction.DOWN)
}
}
ベンチマークを実行する
Android Studio 内からテストを実行して、デバイス上のアプリのパフォーマンスを測定します。図 5 に示すように、テストクラスまたはテストメソッドの横にあるガター アクションを使用して、他の @Test を実行する場合と同じようにベンチマークを実行できます。
または、コマンドラインから connectedCheck コマンドを実行して、Gradle モジュール内のすべてのベンチマークを実行することもできます。
./gradlew :macrobenchmark:connectedCheck以下を実行すると、1 件のテストを実行できます。
./gradlew :macrobenchmark:connectedCheck -P android.testInstrumentationRunnerArguments.class=com.example.macrobenchmark.startup.SampleStartupBenchmark#startup継続的インテグレーションでベンチマークを実行およびモニタリングする方法については、継続的インテグレーションでのベンチマークをご覧ください。
ベンチマークの結果
ベンチマークの実行が成功すると、指標は Android Studio 内に直接表示されます。また、JSON ファイルの CI 使用状況に出力されます。測定される反復処理は、それぞれが個別のシステム トレースをキャプチャします。トレース結果を開くには、図 6 のように、[Test Results] ペインにあるリンクをクリックします。
トレースが読み込まれると、Android Studio によって、分析するプロセスの選択を求められます。図 7 のように、選択フィールドにはターゲット アプリのプロセスが事前入力されます。
トレース ファイルが読み込まれると、Studio は CPU Profiler ツールで結果を表示します。
JSON レポートとプロファイリング トレースも、デバイスからホストに自動的にコピーされます。これらはホストマシンの次の場所に書き込まれます。
project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/
手動でトレース ファイルにアクセスする
Perfetto ツールを使用してトレース ファイルを分析する場合は、追加の手順が必要です。Perfetto では、トレース中にデバイスで実行されているすべてのプロセスを検査できます。これに対して、Android Studio の CPU Profiler では、検査は単一のプロセスに限定されます。
Android Studio から、または Gradle コマンドラインからテストを呼び出した場合、トレース ファイルはデバイスからホストに自動的にコピーされます。これらはホストマシンの次の場所に書き込まれます。
project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/TrivialStartupBenchmark_startup[mode=COLD]_iter002.perfetto-trace
ホストシステムでトレース ファイルが準備できたら、Android Studio の [File] > [Open] メニューからトレース ファイルを開くことができます。前のセクションで示したプロファイラ ツールのビューが表示されます。
構成エラー
アプリが誤ってデバッグ可能またはプロファイル不可に構成されている場合、Macrobenchmark は不正確または不完全な測定をレポートするのではなく、エラーをスローします。androidx.benchmark.suppressErrors 引数を使用すると、このようなエラーの出力を抑制できます。
エミュレータまたは電池容量の少ないデバイスで測定しようとした場合も、コアの可用性とクロック速度が損なわれる可能性があるため、Macrobenchmark はエラーを返します。
ベンチマークをカスタマイズする
measureRepeated 関数は、ライブラリが収集する指標、アプリの起動とコンパイルの方法、ベンチマークの実行対象となる反復処理の数に影響を及ぼすさまざまなパラメータを受け取ります。
指標をキャプチャする
指標は、ベンチマークから抽出される主要な情報タイプです。以下の指標を選択できます。
指標について詳しくは、Macrobenchmark の指標をキャプチャするをご覧ください。
カスタム イベントを使用してトレースデータを改善する
場合によっては、カスタム トレース イベントを使用したアプリのインストルメント化が有用です。カスタム トレース イベントは他のトレース レポートに表示され、アプリ固有の問題を特定するために役立ちます。カスタム トレース イベントの作成方法については、カスタム イベントを定義するをご覧ください。
CompilationMode
Macrobenchmark では、CompilationMode を指定して、アプリのどのくらいの容量を DEX バイトコード(APK 内のバイトコード形式)からマシンコード(プリコンパイル後の C++ のようなコード)にプリコンパイルするかを定義できます。
デフォルトでは、Macrobenchmark は CompilationMode.DEFAULT で実行されます。この場合、Android 7(API レベル 24)以降ではベースライン プロファイル(利用可能な場合)がインストールされます。Android 6(API レベル 23)以前では、このコンパイル モードの場合、デフォルトのシステム動作として APK はフルコンパイルされます。
ターゲット アプリにベースライン プロファイルと ProfileInstaller ライブラリの両方が含まれている場合は、ベースライン プロファイルをインストールできます。
Android 7 以降では、CompilationMode をカスタマイズすることにより、デバイス上のプリコンパイルの量を調整して、さまざまなレベルの事前(AOT)コンパイルまたは JIT キャッシュ処理を模倣できます。CompilationMode.Full、CompilationMode.Partial、CompilationMode.None、CompilationMode.Ignore をご覧ください。
この機能は、ART コンパイル コマンドをベースにして構築されています。ベンチマーク間の干渉が起こらないようにするため、各ベンチマークは開始前にプロファイル データを消去します。
StartupMode
アクティビティの起動を実行するには、事前定義された起動モード(COLD、WARM、HOT のいずれか)を渡します。このパラメータにより、アクティビティの起動方法と、テスト開始時のプロセス状態が変更されます。
起動のタイプについて詳しくは、アプリの起動時間をご覧ください。
サンプル
サンプル プロジェクトは、GitHub のリポジトリの Macrobenchmark のサンプルにあります。
フィードバックを送信
Jetpack Macrobenchmark に関する問題の報告または機能リクエストの送信については、公開されている Issue Trackerをご利用ください。
あなたへのおすすめ
- 注: JavaScript がオフになっている場合はリンクテキストが表示されます
- Macrobenchmark の指標をキャプチャする
- ベースライン プロファイルを作成する {:#creating-profile-rules}
- Macrobenchmark ライブラリで測定を自動化する {:#measuring-optimization}