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ę obrazu.

Makrotesty porównawcze umożliwiają kontrolowanie kompilacji przed pomiarem za pomocą interfejsu API CompilationMode. 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 możesz zobaczyć 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. W przypadku pomiaru i optymalizacji ścieżek kodu niezbędnych do uzyskania w pełni użytecznego stanu aplikacji bardziej przydatny 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 Poprawianie 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]