ベースライン プロファイルの概要

ベースライン プロファイルを使用すると、含まれるコードパスに対して解釈とジャストインタイム(JIT)コンパイルの手順を行う必要がなくなるため、初回起動からのコード実行速度が約 30% 向上します。

ベースライン プロファイルとともにアプリやライブラリをリリースすることで、Android ランタイム(ART)は、事前(AOT)コンパイルによって、指定されるコードパスを最適化し、すべての新規ユーザー、すべてのアプリ アップデートでパフォーマンスを改善できます。このプロファイルに基づく最適化(PGO)を行うと、起動の最適化、インタラクション ジャンクの削減、エンドユーザーの全体的なランタイム パフォーマンスの向上がアプリの初回起動時から可能になります。

こうしたパフォーマンスの向上は、ユーザー維持率、トランザクション、評価などのビジネス指標の改善に直接つながります。パフォーマンスがビジネス指標に及ぼす影響については、JoshLyftTikTokZomato の事例をご覧ください。

ベースライン プロファイルのメリット

ベースライン プロファイルを使用すると、ユーザーの操作(アプリの起動、画面間の移動、コンテンツのスクロールなど)がすべて、初回の実行時からスムーズに行えるようになります。ベースライン プロファイルでアプリの速度と応答性を高めることで、1 日のアクティブ ユーザー数が増加し、平均リピーター率が向上します。

ベースライン プロファイルは、アプリの最初の起動からアプリのランタイムを改善する一般的なユーザー インタラクションを提供して、アプリの起動以外も含めて最適化する際の指針となります。指針に沿った AOT コンパイルは、ユーザーのデバイスに依存せず、モバイル デバイスではなく開発マシンでリリースごとに 1 回実行できます。ベースライン プロファイルとともにアプリをリリースすることで、Cloud プロファイルのみを使用する場合よりもはるかに速く、最適化されたアプリを利用できるようになります。

ベースライン プロファイルを使用しない場合、すべてのアプリコードは解釈後にメモリ内で JIT コンパイルされるか、デバイスがアイドル状態のときにバックグラウンドで odex ファイルに書き込まれます。アプリをインストールまたは更新した後、初回の実行時から新しいコードパスが最適化されるまで、ユーザーは最適なパフォーマンスが得られません。多くのアプリで、最適化後にパフォーマンスが約 30% 向上することがわかっています。

起動プロファイル

起動プロファイルはベースライン プロファイルと類似していますが、デバイス上の最適化のためではなく、コンパイル時に使用される点が異なります。起動プロファイルは、DEX ファイルのレイアウトを最適化して起動時間を短縮するために使用されます。起動プロファイルで識別されたコードはプライマリ classes.dex ファイルに配置され、その他のコードは個別の DEX ファイルに配置されます。これにより、アプリ起動時のページ フォールトの発生数が減少し、起動時間が短縮されます。起動プロファイルと DEX レイアウトの最適化によってアプリの起動時間を短縮する方法について詳しくは、DEX レイアウトの最適化と起動プロファイルをご覧ください。

始める

既存のアプリでパフォーマンスの最適化を行うには、ベースライン プロファイルの作成をご覧ください。

依存関係チェーンでは、安定版リリース バージョンと開発リリース バージョンが提供されます。ベースライン プロファイルを生成してインストールするには、Android Gradle プラグイン、Macrobenchmark ライブラリ、プロファイル インストーラの下記の対応バージョン以上を使用してください。これらの依存関係は異なるタイミングで必要になり、最適なベースライン プロファイルを実現するツールチェーンとして連携して機能します。

  • Android Gradle プラグイン: com.android.tools.build:8.0.0
  • Macrobenchmark ライブラリ: androidx.benchmark:benchmark-macro-junit4:1.2.3
  • プロファイル インストーラ: androidx.profileinstaller:profileinstaller:1.3.1

ベースライン プロファイルの作成と管理には、最新バージョンの AGP を使用することをおすすめします。AGP のバージョン別の主な機能は次のとおりです。

AGP バージョン 機能
8.3
  • 完全なソースセット ディレクトリのサポート(ライブラリ モジュール): 複数のベースライン プロファイルのソースファイルを宣言し、バリアントに対応したディレクトリ(src/free/generated/baselineProfiles/baseline-prof1.txt など)をライブラリ モジュールだけでなくアプリ モジュールにも使用できるようになりました。
8.2
  • R8 のルールの書き換え: D8 と R8 は、人が読める形式のベースライン プロファイル ルールと起動プロファイル ルールを変換し、アプリのパフォーマンスを最適化するために必要なすべてのルールを完全にキャプチャできます。メソッドのベースライン プロファイルのカバレッジが最大で 30% 増加し、アプリのパフォーマンスが最大で 15% 向上します。
  • 起動プロファイル: この新しいタイプのベースライン プロファイルを生成して、DEX 内のコードのレイアウトを伝えます。起動のパフォーマンスがさらに最大で 15% 向上します。大規模なアプリでは、このパフォーマンスはより大きく向上します。
8.0 推奨最小バージョン: ベースライン プロファイル Gradle プラグインを使用し、単一の Gradle タスクでベースライン プロファイルを生成します。
  • 完全なソースセット ディレクトリのサポート(ライブラリ モジュール): 複数のベースライン プロファイルのソースファイルを宣言し、バリアントに対応したディレクトリ(src/free/generated/baselineProfiles/baseline-prof1.txt など)を使用できるようになりました。
7.4 サポートされる最小バージョン: アプリは、ライブラリからベースライン プロファイルを使用し、src/main/baseline-prof.txt ファイルで独自のベースライン プロファイルを提供できます。
  • App Bundle から APK をビルドすると、ベースライン プロファイルが正しくパッケージ化されます(問題 #230361284)。
  • 複数の .dex ファイルがあるアプリの場合、ベースライン プロファイルはプライマリ .dex ファイルに対して正しくパッケージ化されます。

プロファイル生成の例

アプリ起動用のベースライン プロファイルに加えて、推奨される Macrobenchmark ライブラリを使用したナビゲーション イベントおよびスクロール イベントを作成するクラスの例を以下に示します。

@OptIn(ExperimentalBaselineProfilesApi::class)
class BaselineProfileGenerator {
    @get:Rule
    val baselineProfileRule = BaselineProfileRule()

    @Test
    fun appStartupAndUserJourneys() {
        baselineProfileRule.collect(packageName = PACKAGE_NAME) {
            // App startup journey.
            startActivityAndWait()

            device.findObject(By.text("COMPOSE LAZYLIST")).clickAndWait(Until.newWindow(), 1_000)
            device.findObject(By.res("myLazyColumn")).also {
                it.fling(Direction.DOWN)
                it.fling(Direction.UP)
            }
            device.pressBack()
        }
    }
}

このコードは GitHub のパフォーマンス サンプルに含まれており、コンテキストの全体および詳細情報と合わせて確認できます。

追加すべき要素

アプリでベースライン プロファイルを使用する場合、アプリの起動コードと、画面間のナビゲーションやスクロールなどの一般的なユーザー操作を含めることができます。登録、ログイン、支払いなどのフロー全体を収集することも可能です。重要と判断したユーザー ジャーニーについては、ベースライン プロファイルを利用することで、ランタイム パフォーマンスを改善できます。

パフォーマンスを改善するさまざまな方法をテストしている場合は、両方のテスト群にベースライン プロファイルを含めることを検討してください。両方に含めることにより、コンパイル済みのコードをすべてのユーザーが同様に実行するようになり、結果を解釈しやすくなります。

ライブラリが提供する独自のベースライン プロファイルをリリースの際に配布することで、アプリのパフォーマンスを改善できます。たとえば、Jetpack Compose のパフォーマンスについてのページで「ベースライン プロファイルを使用する」セクションをご覧ください。

ベースライン プロファイルの仕組み

アプリやライブラリの開発でベースライン プロファイルを定義する際は、レンダリング時間やレイテンシが重要となる一般的なユーザー操作がカバーされるようにしてください。 仕組みは次のとおりです。

  1. 人間が判読できる形式でプロファイル ルールがアプリ用に生成され、アプリ内でバイナリ形式にコンパイルされます(assets/dexopt/baseline.prof にあります)。その後、AAB を通常どおり Google Play にアップロードできます。

  2. Google Play がプロフィールを処理し、APK とともにユーザーに直接リリースします。インストール時に、ART はプロファイル内のメソッドを AOT コンパイルします。これにより、メソッドの実行速度が向上します。アプリの起動時やフレーム レンダリング時に使用されるメソッドがプロファイルに含まれていれば、起動時間が短くなったり、ジャンクが減ったりする可能性があります。

  3. このフローはクラウド プロファイルの集約と連携し、時間の経過とともに、アプリの実際の使用に基づいてパフォーマンスを微調整します。

図 1. この図は、アップロードからエンドユーザーへの配信までの、ベースライン プロファイルのワークフローと、そのワークフローがクラウド プロファイルとどのように関連しているかを示しています。

クラウド プロファイル

クラウド プロファイルでは、追加の形式の PGO がベースライン プロファイルとともに提供されます。PGO は Google Play ストアで集約され、インストール時のコンパイル用に配布されます。

クラウド プロファイルは実際のユーザーによるアプリの操作によって機能しますが、更新が配信されるまで数時間から数日かかるため、可用性が制限されます。プロファイルが完全に配信されるまで、新しいアプリまたは更新されたアプリのユーザーは、アプリを最適なパフォーマンスで利用できません。また、クラウド プロファイルは、Android 9(API レベル 28)以上を搭載した Android デバイスのみに対応しており、ユーザーが一定数以上いるアプリにのみ適しています。

Android バージョン間のコンパイル動作

Android プラットフォームの各バージョンでは、さまざまなアプリのコンパイル方法が採用されており、それぞれの方法にパフォーマンス面でのトレードオフがあります。ベースライン プロファイルは、すべてのインストールにプロファイルを提供することで、以前のコンパイル方法を改善します。

Android のバージョン コンパイル方法 最適化アプローチ
5~6(API レベル 21~23) 完全 AOT アプリ全体がインストール時に最適化されるため、アプリ使用時の待ち時間が長くなって RAM やディスクの使用量が増えます。また、ディスクからコードを読み込む時間が長くなるため、コールド スタートアップに時間がかかることがあります。
7 ~ 8.1(API レベル 24 ~ 27) 部分 AOT(ベースライン プロファイル) アプリ モジュールで依存関係が定義されている場合は、初回実行時に androidx.profileinstaller によってベースライン プロファイルがインストールされます。ART は、アプリ使用時に他のプロファイル ルールを追加し、デバイスがアイドル状態のときにそれらをコンパイルすることで、ベースライン プロファイルの内容をさらに改善できます。これにより、ディスク容量と、ディスクからコードを読み込む時間が最適化され、アプリの待ち時間が短くなります。
9(API レベル 28) 以降 部分 AOT(ベースライン + クラウド プロファイル) Google Play がアプリのインストール時にベースライン プロファイルを使用し、APK とクラウド プロファイル(利用可能な場合)を最適化します。インストール後、ART プロファイルは Google Play にアップロードされ、集約されます。集約されたプロファイルは、後日他のユーザーがアプリをインストールまたは更新する際にクラウド プロファイルとして提供されます。

考えられる問題への解決策

考えられる問題と解決策、回避策を開発中の問題は次のとおりです。

  • 脱糖されたクラスがベースライン プロファイルに含まれません。脱糖されたクラスは、ベースライン プロファイルをサポートしていない別のビルドプロセスによって最終的な APK に追加されるため、欠落する可能性があります。この問題は Android Studio Iguana Canary 8 で修正されています(問題 #283947063)。

  • user(root 権限のない)ビルドで、ART プロファイル キャッシュをリセットできません。この問題を回避するために、androidx.benchmark:benchmark-macro-junit4:1.1.0 にはベンチマーク中にアプリを再インストールする修正が含まれています(問題)。

  • Android Studio のプロファイラで、アプリのプロファイリング時にベースライン プロファイルがインストールされません(問題)。

  • Gradle 以外のビルドシステム(Bazel や Buck など)では、ベースライン プロファイルを出力 APK にコンパイルできません。

  • Google Play ストア以外のアプリ配信チャネルでは、インストール時にベースライン プロファイルを使用できない場合があります。こうしたチャネルを通じてインストールされたアプリをユーザーが使用することは、バックグラウンド dexopt が実行されるまで(通常一晩中)メリットがありません。

  • Play ストア内部アプリ共有はベースライン プロファイルをサポートしていませんが、内部テストトラックはサポートしています。

  • バッテリーを最適化すると、プロファイルのインストールが妨げられることがあります。プロファイルを効果的にインストールできるようにするには、ベンチマーク デバイスでバッテリーの最適化を無効にしてください。

  • ベンチマークと本番環境とでは、パフォーマンスの改善に差が生じることがあります。これは、ローカル ベンチマークでパフォーマンスを測定する際に、ベースライン プロファイルが有効な場合と無効な場合があるためです。本番環境のアプリでは、アプリの新しい部分がベースライン プロファイルに追加されると、その部分がコントリビューション ライブラリを介してプロファイリングされた状態になるため、測定値が向上します。

  • ライブラリにベースライン プロファイルを適切に提供するには、ベースライン プロファイル Gradle プラグイン 1.2.3 以降を使用することをおすすめします。代わりに AGP 8.3 以降を使用することもできます。詳しくは、問題 #313992099 をご覧ください。

参考情報