Macrobenchmark ライブラリを使用したベースライン プロファイルのベンチマーク

Jetpack Macrobenchmark を使用して、ベースライン プロファイルが有効になっている場合と無効になっている場合でアプリの動作をテストし、結果を比較することをおすすめします。このアプローチでは、アプリの起動時間(初期表示までの時間と完全表示までの時間)または実行時のレンダリング パフォーマンスを測定して、生成されたフレームがジャンクを引き起こすかどうかを確認できます。

Macrobenchmark では、CompilationMode API を使用して、測定前のコンパイルを制御できます。異なる CompilationMode 値を使用して、コンパイル状態ごとに異なるパフォーマンスを比較します。次のコード スニペットは、CompilationMode パラメータを使用してベースライン プロファイルのメリットを測定する方法を示しています。

@RunWith(AndroidJUnit4ClassRunner::class)
class ColdStartupBenchmark {
    @get:Rule
    val benchmarkRule = MacrobenchmarkRule()

    // No ahead-of-time (AOT) compilation at all. Represents performance of a
    // fresh install on a user's device if you don't enable Baseline Profiles—
    // generally the worst case performance.
    @Test
    fun startupNoCompilation() = startup(CompilationMode.None())

    // Partial pre-compilation with Baseline Profiles. Represents performance of
    // a fresh install on a user's device.
    @Test
    fun startupPartialWithBaselineProfiles() =
        startup(CompilationMode.Partial(baselineProfileMode = BaselineProfileMode.Require))

    // Partial pre-compilation with some just-in-time (JIT) compilation.
    // Represents performance after some app usage.
    @Test
    fun startupPartialCompilation() = startup(
        CompilationMode.Partial(
            baselineProfileMode = BaselineProfileMode.Disable,
            warmupIteration = 3
        )
    )

    // Full pre-compilation. Generally not representative of real user
    // experience, but can yield more stable performance metrics by removing
    // noise from JIT compilation within benchmark runs.
    @Test
    fun startupFullCompilation() = startup(CompilationMode.Full())

    private fun startup(compilationMode: CompilationMode) = benchmarkRule.measureRepeated(
        packageName = "com.example.macrobenchmark.target",
        metrics = listOf(StartupTimingMetric()),
        compilationMode = compilationMode,
        iterations = 10,
        startupMode = StartupMode.COLD,
        setupBlock = {
            pressHome()
        }
    ) {
        // Waits for the first rendered frame, which represents time to initial display.
        startActivityAndWait()

        // Waits for content to be visible, which represents time to fully drawn.
        device.wait(Until.hasObject(By.res("my-content")), 5_000)
    }
}

次のスクリーンショットでは、Google Pixel 7 で実行された Now in Android サンプルアプリの結果を Android Studio で直接確認できます。この結果から、コンパイルなし(324.8 ms)とは対照的に、ベースライン プロファイルを使用した場合にアプリは最速で起動する(229.0 ms)ことがわかります。

ColdstartupBenchmark の結果
図 1. ColdStartupBenchmark には初期表示までの時間が示されています。結果は、コンパイルなし(324 ms)、フルコンパイル(315 ms)、部分コンパイル(312 ms)、ベースライン プロファイル(229 ms)となりました。

前述の例では、StartupTimingMetric でキャプチャしたアプリの起動結果が示されていますが、他にも FrameTimingMetric など、検討すべき重要な指標があります。指標の全種類について詳しくは、Macrobenchmark の指標をキャプチャするをご覧ください。

完全表示までの時間

前述の例では、初期表示までの時間(TTID)を測定しています。これは、アプリが最初のフレームを生成するのに要する時間です。ただし、これは必ずしもユーザーがアプリの操作を開始できるようになるまでの時間を示しているわけではありません。アプリを完全に使用できる状態にするのに必要なコードパスを測定して最適化するうえでは、完全表示までの時間(TTFD)指標のほうがより有益です。

TTID と TTFD はともに重要であるため、いずれも最適化することをおすすめします。TTID が短ければ、アプリが実際に起動されていることをユーザーが確認しやすくなります。一方、ユーザーがすぐにアプリを操作できるようにするために、TTFD を短くしておくことは重要です。

アプリ UI が完全に描画されたときの通知に関する戦略については、起動時間の精度を改善するをご覧ください。

  • 注: JavaScript がオフになっている場合はリンクテキストが表示されます
  • [Macrobenchmark を作成する][11]
  • [Macrobenchmark の指標をキャプチャする][12]
  • [アプリの起動の分析と最適化]{:#app-startup-analysis-optimization}[13]