Porównywanie profili podstawowych za pomocą biblioteki Macrobenchmark

Zalecamy używanie Jetpack Macrobenchmark do testowania wydajności aplikacji, gdy profile bazowe są włączone, a następnie porównywanie tych wyników z wartościami referencyjnymi, gdy profile bazowe są wyłączone. Dzięki temu możesz mierzyć czas uruchamiania aplikacji – zarówno czas do wyświetlenia początkowego, jak i pełnego – lub wydajność renderowania w czasie działania, aby sprawdzić, czy wygenerowane klatki mogą powodować zacinanie się.

Makrotesty porównawcze umożliwiają kontrolowanie kompilacji przed pomiarem za pomocą interfejsu CompilationMode API. Użyj różnych wartości CompilationMode, aby porównać skuteczność w różnych stanach kompilacji. Poniższy fragment kodu pokazuje, jak używać parametru CompilationMode do pomiaru korzyści z profili podstawowych:

@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)
    }
}

Na zrzucie ekranu poniżej widać wyniki bezpośrednio w Android Studio w przypadku przykładowej aplikacji Now in Android uruchomionej na Google Pixelu 7. Wyniki pokazują, że aplikacja uruchamia się najszybciej w przypadku użycia profili podstawowych (229,0 ms) w porównaniu z brakiem kompilacji (324,8 ms).

wyniki testu ColdstartupBenchmark,
Rysunek 1. Wyniki ColdStartupBenchmark pokazujące czas do pierwszego wyświetlenia w przypadku braku kompilacji (324 ms), pełnej kompilacji (315 ms), częściowej kompilacji (312 ms) i profili podstawowych (229 ms).

W poprzednim przykładzie pokazano wyniki uruchamiania aplikacji zarejestrowane za pomocą funkcji StartupTimingMetric. Warto jednak wziąć pod uwagę inne ważne dane, takie jak FrameTimingMetric. Więcej informacji o wszystkich rodzajach danych znajdziesz w artykule Zbieranie danych testów porównawczych.

Czas do pełnego wyświetlenia

W poprzednim przykładzie mierzony jest czas do początkowego wyświetlania (TTID), czyli czas potrzebny aplikacji na wygenerowanie pierwszej klatki. Nie musi to jednak odzwierciedlać czasu, po którym użytkownik może zacząć korzystać z aplikacji. Bardziej przydatny do pomiaru i optymalizacji ścieżek kodu niezbędnych do uzyskania w pełni użytecznego stanu aplikacji jest wskaźnik czasu do pełnego wyświetlenia (TTFD).

Zalecamy optymalizację zarówno pod kątem TTID, jak i TTFD, ponieważ oba te wskaźniki są ważne. Niski czas TTID pomaga użytkownikowi zauważyć, że aplikacja faktycznie się uruchamia. Krótki czas TTFD jest ważny, ponieważ pozwala użytkownikowi szybko wejść w interakcję z aplikacją.

Strategie raportowania, gdy interfejs aplikacji jest w pełni narysowany, znajdziesz w artykule Zwiększanie dokładności czasu uruchamiania.

  • Uwaga: tekst linku jest wyświetlany, gdy JavaScript jest wyłączony.
  • [Tworzenie testu porównawczego][11]
  • [Zbieranie danych makrobenchmarków][12]
  • [Analiza i optymalizacja uruchamiania aplikacji {:#app-startup-analysis-optimization}][13]