ベースライン プロファイルを作成する

Jetpack Macrobenchmark ライブラリBaselineProfileRule を使用して、アプリのリリースごとにプロファイルを自動的に生成します。ベースライン プロファイルを使用する場合は、ビルドが改善されている com.android.tools.build:gradle:8.0.0 以降を使用することをおすすめします。

新しいベースライン プロファイルを作成する一般的な手順は次のとおりです。

  1. ベースライン プロファイル モジュールをセットアップします。
  2. ベースライン プロファイルの生成に役立つ JUnit テストを定義します。
  3. 最適化するクリティカル ユーザー ジャーニー(CUJ)を追加します。
  4. ベースライン プロファイルを生成します。

ベースライン プロファイルを生成したら、実機を使用してベンチマークを行い、速度の向上を測定します。

AGP 8.2 以降で新しいベースライン プロファイルを作成する

新しいベースライン プロファイルを作成する最も簡単な方法は、Android Studio Iguana と Android Gradle プラグイン(AGP)8.2 以降で利用可能なベースライン プロファイル モジュール テンプレートを使用することです。

Android Studio ベースライン プロファイル ジェネレータ モジュール テンプレートを使用すると、ベースライン プロファイルの生成とベンチマークを行うための新しいモジュールの作成を自動化できます。テンプレートを実行すると、一般的なビルド構成、ベースライン プロファイル生成、検証コードのほとんどが生成されます。このテンプレートにより、ベースライン プロファイルの生成とベンチマークを行ってアプリの起動時間を測定するためのコードが作成されます。

ベースライン プロファイル モジュールをセットアップする

ベースライン プロファイル モジュール テンプレートを実行する手順は、次のとおりです。

  1. [File] > [New] > [New Module] を選択します。
  2. [Templates] パネルで [Baseline Profile Generator] テンプレートを選択し、構成します。
    図 1.ベースライン プロファイル ジェネレータ モジュール テンプレート

    テンプレートの各フィールドは次のとおりです。

    • Target application: ベースライン プロファイルを生成するアプリを定義。プロジェクトにアプリ モジュールが 1 つしかない場合、このリストにはアイテムが 1 つだけになります。
    • Module name: 作成されるベースライン プロファイル モジュールに付ける名前。
    • Package name: ベースライン プロファイル モジュールに付けるパッケージ名。
    • Language: 生成されるコードを Kotlin にするか Java にするか。
    • Build configuration language: ビルド構成スクリプトに Kotlin スクリプト(KTS)と Groovy のどちらを使用するか。
    • Gradle で管理されているデバイスを使用する: Gradle で管理されているデバイスを使用してアプリをテストするかどうか。
  3. [Finish] をクリックすると、新しいモジュールが作成されます。ソース管理を使用している場合は、新しく作成されたモジュール ファイルをソース管理に追加するよう求められることがあります。

ベースライン プロファイル ジェネレータを定義する

新しく作成されたモジュールには、ベースライン プロファイルの生成とベンチマークの両方を実行し、基本的なアプリの起動時間のみをテストするテストが含まれています。これらに CUJ と高度な起動ワークフローを含めることをおすすめします。アプリの起動に関連するテストはすべて、includeInStartupProfiletrue に設定した rule ブロックに配置してください。逆に、最適なパフォーマンスを得るには、アプリの起動に関係のないテストを起動プロファイルに含めないようにします。アプリの起動の最適化は、ベースライン プロファイルの特別な部分である起動プロファイルを定義するために使用されます。

生成されたベースライン プロファイルとベンチマーク コードの外部で CUJ を抽象化すると、両方で使用できるため、メンテナンスが容易になります。つまり、CUJ に対する変更が常に使用されるということです。

ベースライン プロファイルを生成してインストールする

ベースライン プロファイル モジュール テンプレートにより、新しい実行構成が追加され、ベースライン プロファイルが生成されます。プロダクト フレーバーを使用している場合、Android Studio は複数の実行構成を作成し、フレーバーごとに個別のベースライン プロファイルを生成します。

ベースライン プロファイル生成の実行構成。
図 2. この構成を実行すると、ベースライン プロファイルが生成される。

Generate Baseline Profile 実行構成が完了すると、プロファイリングされるモジュールの src/variant/generated/baselineProfiles/baseline-prof.txt ファイルに、生成されたベースライン プロファイルがコピーされます。バリアント オプションは、リリースビルド タイプ、またはリリースビルド タイプを含むビルド バリアントのいずれかです。

生成されたベースライン プロファイルは build/outputs に作成されます。フルパスは、プロファイリングされるアプリのバリアントまたはフレーバーと、プロファイリングに Gradle で管理されているデバイスと接続されたデバイスのどちらを使用するかによって決まります。コードで使用された名前とテンプレートによって生成されたビルド構成を使用すると、ベースライン プロファイルが build/outputs/managed_device_android_test_additional_output/nonminifiedrelease/pixel6Api31/BaselineProfileGenerator_generate-baseline-prof.txt ファイルに作成されます。生成されたベースライン プロファイルのこのバージョンを直接操作する必要はありません。ただし、手動でターゲット モジュールにコピーする場合を除きます(非推奨)。

AGP 8.1 で新しいベースライン プロファイルを作成する

ベースライン プロファイル モジュール テンプレートを使用できない場合は、Macrobenchmark モジュール テンプレートとベースライン プロファイル Gradle プラグインを使用して、新しいベースライン プロファイルを作成します。これらのツールは、Android Studio Giraffe と AGP 8.1 以降に使用することをおすすめします。

Macrobenchmark モジュール テンプレートとベースライン プロファイル Gradle プラグインを使用して新しいベースライン プロファイルを作成する手順は次のとおりです。

  1. Gradle プロジェクトに Macrobenchmark モジュールをセットアップします。
  2. BaselineProfileGenerator という新しいクラスを定義します。
    class BaselineProfileGenerator {
        @get:Rule
        val baselineProfileRule = BaselineProfileRule()
    
        @Test
        fun startup() = baselineProfileRule.collect(
            packageName = "com.example.app",
            profileBlock = {
                startActivityAndWait()
            }
        )
    }

    ジェネレータには、アプリの起動以外の操作を含めることができます。これにより、リストのスクロール、アニメーションの実行、Activity 内での移動など、アプリのランタイム パフォーマンスの最適化が可能となります。@BaselineProfileRule を使用してクリティカル ユーザー ジャーニーを改善するテストについて、その他の例もご覧になれます。

  3. ベースライン プロファイル Gradle プラグイン(libs.plugins.androidx.baselineprofile)を追加します。このプラグインを使用すると、ベースライン プロファイルの生成と将来のメンテナンスが容易になります。

  4. ベースライン プロファイルを生成するには、ターミナルで Gradle タスク :app:generateBaselineProfile または :app:generateVariantBaselineProfile を実行します。

    ジェネレータは、root 権限取得の実機、エミュレータ、Gradle で管理されているデバイスのいずれかでインストルメンテーション テストとして実行します。Gradle で管理されているデバイスを使用する場合は、ベースライン プロファイル ジェネレータに root アクセス権が必要なため、aospsystemImageSource に設定します。

    生成タスクが終了すると、ベースライン プロファイルが app/src/variant/generated/baselineProfiles にコピーされます。

テンプレートなしで新しいベースライン プロファイルを作成する

Android Studio のベースライン プロファイル モジュール テンプレート(推奨)または Macrobenchmark テンプレートを使用してベースライン プロファイルを作成することをおすすめしますが、ベースライン プロファイル Gradle プラグインをお使いいただくことも可能です。ベースライン プロファイル Gradle プラグインの詳細については、ベースライン プロファイルの生成を構成するをご覧ください。

ベースライン プロファイルの Gradle プラグインを直接使用してベースライン プロファイルを作成する手順は次のとおりです。

  1. 新しい com.android.test モジュールを作成します(例: :baseline-profile)。
  2. :baseline-profilebuild.gradle.kts ファイルを構成します。

    1. androidx.baselineprofile プラグインを適用します。
    2. targetProjectPath:app モジュールを参照していることを確認します。
    3. 必要に応じて、Gradle で管理されているデバイス(GMD)を追加します。以下の例では、pixel6Api31 です。指定しなかった場合、プラグインは接続されているデバイス(エミュレータまたは実機)を使用します。
    4. 次の例に示すように、必要な設定を適用します。

    Kotlin

    plugins {
        id("com.android.test")
        id("androidx.baselineprofile")
    }
    
    android {
        defaultConfig {
            ...
        }
    
        // Point to the app module, the module that you're generating the Baseline Profile for.
        targetProjectPath = ":app"
        // Configure a GMD (optional).
        testOptions.managedDevices.devices {
            pixel6Api31(com.android.build.api.dsl.ManagedVirtualDevice) {
                device = "Pixel 6"
                apiLevel = 31
                systemImageSource = "aosp"
            }
        }
    }
    
    dependencies { ... }
    
    // Baseline Profile Gradle plugin configuration. Everything is optional. This
    // example uses the GMD added earlier and disables connected devices.
    baselineProfile {
        // Specifies the GMDs to run the tests on. The default is none.
        managedDevices += "pixel6Api31"
        // Enables using connected devices to generate profiles. The default is
        // `true`. When using connected devices, they must be rooted or API 33 and
        // higher.
        useConnectedDevices = false
    }

    Groovy

    plugins {
        id 'com.android.test'
        id 'androidx.baselineprofile'
    }
    
    android {
        defaultConfig {
            ...
        }
    
        // Point to the app module, the module that you're generating the Baseline Profile for.
        targetProjectPath ':app'
        // Configure a GMD (optional).
        testOptions.managedDevices.devices {
            pixel6Api31(com.android.build.api.dsl.ManagedVirtualDevice) {
                device 'Pixel 6'
                apiLevel 31
                systemImageSource 'aosp'
            }
        }
    }
    
    dependencies { ... }
    
    // Baseline Profile Gradle plugin configuration. Everything is optional. This
    // example uses the GMD added earlier and disables connected devices.
    baselineProfile {
        // Specifies the GMDs to run the tests on. The default is none.
        managedDevices ['pixel6Api31']
        // Enables using connected devices to generate profiles. The default is
        // `true`. When using connected devices, they must be rooted or API 33 and
        // higher.
        useConnectedDevices false
    }
  3. :baseline-profile テスト モジュールでベースライン プロファイル テストを作成します。次の例は、アプリを起動してアイドル状態になるのを待つテストです。

    Kotlin

    class BaselineProfileGenerator {
    
        @get:Rule
        val baselineRule = BaselineProfileRule()
    
        @Test
        fun startupBaselineProfile() {
            baselineRule.collect("com.myapp") {
                startActivityAndWait()
            }
        }
    }

    Java

    public class BaselineProfileGenerator {
    
        @Rule
        Public BaselineProfileRule baselineRule = new BaselineProfileRule();
    
        @Test
        Public void startupBaselineProfile() {
            baselineRule.collect(
                "com.myapp",
                (scope -> {
                    scope.startActivityAndWait();
                    Return Unit.INSTANCE;
                })
            )
        }
    }
  4. アプリ モジュールの build.gradle.kts ファイルを更新します(:app など)。

    1. プラグイン androidx.baselineprofile を適用します。
    2. baselineProfile 依存関係を :baseline-profile モジュールに追加します。

    Kotlin

    plugins {
        id("com.android.application")
        id("androidx.baselineprofile")
    }
    
    android {
        // There are no changes to the `android` block.
        ...
    }
    
    dependencies {
        ...
        // Add a `baselineProfile` dependency on the `:baseline-profile` module.
        baselineProfile(project(":baseline-profile"))
    }

    Groovy

    plugins {
        id 'com.android.application'
        id 'androidx.baselineprofile'
    }
    
    android {
        // No changes to the `android` block.
        ...
    }
    
    dependencies {
        ...
        // Add a `baselineProfile` dependency on the `:baseline-profile` module.
        baselineProfile ':baseline-profile'
    }
  5. プロファイルを生成するには、Gradle タスク :app:generateBaselineProfile または :app:generateVariantBaselineProfile を実行します。

  6. 生成タスクが終了すると、ベースライン プロファイルが app/src/variant/generated/baselineProfiles にコピーされます。

AGP 7.3~7.4 で新しいベースライン プロファイルを作成する

AGP 7.3~7.4 でベースライン プロファイルを生成することは可能ですが、ベースライン プロファイル Gradle プラグインとその最新機能を使用できるように、AGP 8.1 以降にアップグレードすることを強くおすすめします。

AGP 7.3~7.4 でベースライン プロファイルを作成する必要がある場合、以下の点を除き、AGP 8.1 の手順と同じです。

生成されたルールを手動で適用する

ベースライン プロファイル ジェネレータにより、人が読める形式(HRF)のテキスト ファイルがデバイスで作成され、ホストマシンにコピーされます。生成されたプロファイルをコードに適用する手順は次のとおりです。

  1. プロファイルを生成したモジュールの build フォルダ([module]/build/outputs/managed_device_android_test_additional_output/[device])にある HRF ファイルを見つけます。

    プロファイルは、[class name]-[test method name]-baseline-prof.txt という命名パターンに従います(例: BaselineProfileGenerator-startup-baseline-prof.txt)。

  2. 生成されたプロファイルを src/main/ にコピーし、ファイルの名前を baseline-prof.txt に変更します。

  3. アプリの build.gradle.kts ファイルで ProfileInstaller ライブラリに依存関係を追加し、クラウド プロファイルを利用できないローカルのベースライン プロファイルのコンパイルを有効にします。これは、ベースライン プロファイルをローカルでサイドローディングする唯一の方法です。

    dependencies {
         implementation("androidx.profileinstaller:profileinstaller:1.4.1")
    }
    
  4. アプリの製品版をビルドします。その際、適用された HRF ルールがバイナリ形式にコンパイルされて APK または AAB に追加されます。ビルドしたら、通常どおりアプリを配信します。

ベースライン プロファイルのベンチマークを行う

ベースライン プロファイルのベンチマークを行うには、StartupBenchmarks.kt または StartupBencharks.java ファイルで定義されたベンチマークを実行するガター アクションから新しい Android Instrumented Test Run 構成を作成します。ベンチマーク テストの詳細については、Macrobenchmark クラスを作成するMacrobenchmark ライブラリで測定を自動化するをご覧ください。

図 3. ガター アクションから Android テストを実行する

これを Android Studio 内で実行すると、ベースライン プロファイルから得られる速度改善の詳細がビルド出力に含まれます。

StartupBenchmarks_startupCompilationBaselineProfiles
timeToInitialDisplayMs   min 161.8,   median 178.9,   max 194.6
StartupBenchmarks_startupCompilationNone
timeToInitialDisplayMs   min 184.7,   median 196.9,   max 202.9

必要なコードパスをすべてキャプチャする

アプリの起動時間を測定するための主な 2 つの指標は次のとおりです。

最初の表示までの時間(TTID)
アプリの UI の最初のフレームを表示するのにかかる時間。
完全表示までの時間(TTFD)
TTID と、最初のフレームが表示された後に非同期で読み込まれるコンテンツを表示する時間の合計。

TTFD は、ComponentActivityreportFullyDrawn() メソッドが呼び出されると報告されます。reportFullyDrawn() が呼び出されない場合、代わりに TTID が報告されます。reportFullyDrawn() が呼び出されるタイミングを、非同期読み込みが完了するまで遅延することが必要になる場合があります。たとえば、UI に RecyclerView遅延リストなどの動的リストが含まれている場合、リストが最初に描画された後、つまり UI が完全に描画されたとマークされた後で完了するバックグラウンド タスクによって、データが入力される場合があります。このような場合、UI が完全に描画された状態になった後で実行されたコードは、ベースライン プロファイルに含まれません。

リストへのデータ入力をベースライン プロファイルに含めるには、getFullyDrawnReporter() を使用して FullyDrawnReporter を取得し、アプリコードでレポーターを追加します。バックグラウンド タスクでリストへのデータ入力が完了したらレポーターを解放します。すべてのレポーターが解放されるまで、FullyDrawnReporterreportFullyDrawn() メソッドを呼び出すことはありません。こうすることで、ベースライン プロファイルにリストへのデータ入力に必要なコードパスが含まれるようになります。これにより、ユーザーにとってのアプリの動作が変わることはありませんが、ベースライン プロファイルには必要なすべてのコードパスが含まれるようになります。

アプリで Jetpack Compose を使用している場合は、以下の API を使用して完全に描画された状態を示します。

  • ReportDrawn は、コンポーザブルで直ちにインタラクションが発生する準備が整っていることを示します。
  • ReportDrawnWhen は、コンポーザブルでインタラクションの準備が整ったタイミングを示す list.count > 0 などの述語を受け取ります。
  • ReportDrawnAfter は、完了時にインタラクションの準備が整ったことを示す停止中のメソッドを受け取ります。