Tworzenie profili podstawowych

Profile podstawowe są niezbędne do maksymalizacji wydajności Jetpack Compose. Wstępna kompilacja najważniejszych ścieżek użytkownika pomaga zapewnić płynne renderowanie interfejsu Compose.

Automatycznie generuj profile dla każdej wersji aplikacji za pomocą biblioteki Jetpack Macrobenchmark i BaselineProfileRule. Aby korzystać z ulepszeń kompilacji podczas używania profili podstawowych, zalecamy używanie wersji com.android.tools.build:gradle:8.0.0 lub nowszej.

Oto ogólne kroki tworzenia nowego profilu podstawowego:

  1. Skonfiguruj moduł profilu podstawowego.
  2. Zdefiniuj test JUnit, który pomaga generować profile podstawowe.
  3. Dodaj najważniejsze ścieżki użytkownika, które chcesz zoptymalizować.
  4. Wygeneruj profil podstawowy.

Po wygenerowaniu profilu podstawowego przeprowadź test porównawczy na urządzeniu fizycznym, aby zmierzyć wzrost szybkości.

Tworzenie nowego profilu podstawowego za pomocą AGP 8.2 lub nowszego

Najłatwiejszym sposobem utworzenia nowego profilu podstawowego jest użycie szablonu modułu profilu podstawowego, który jest dostępny od wersji Android Studio Iguana i wtyczki Androida do obsługi Gradle (AGP) 8.2.

Szablon modułu generatora profilu podstawowego w Android Studio automatyzuje tworzenie nowego modułu do generowania i testowania porównawczego profili podstawowych. Uruchomienie szablonu generuje większość typowej konfiguracji kompilacji, profilu podstawowego oraz kodu weryfikacyjnego. Szablon tworzy kod do generowania i testowania porównawczego profili podstawowych w celu pomiaru czasu uruchamiania aplikacji.

Konfigurowanie modułu profilu podstawowego

Aby uruchomić szablon modułu profilu podstawowego, wykonaj te czynności:

  1. Kliknij Plik > Nowy > Nowy moduł.
  2. W panelu Szablony wybierz szablon Generator profilu podstawowego i skonfiguruj go:
    Rysunek 1. Szablon modułu generatora profilu podstawowego.
    Pola w szablonie to:
    • Aplikacja docelowa: aplikacja, dla której generowany jest profil podstawowy. Jeśli w projekcie masz tylko 1 moduł aplikacji, na tej liście będzie tylko 1 element.
    • Nazwa modułu: nazwa, którą chcesz nadać tworzonemu modułowi profilu podstawowego.
    • Nazwa pakietu: nazwa pakietu, którą chcesz nadać modułowi profilu podstawowego.
    • Język: czy wygenerowany kod ma być w Kotlinie czy w Javie.
    • Język konfiguracji kompilacji: czy chcesz używać skryptu Kotlin (KTS) czy Groovy w skryptach konfiguracji kompilacji.
    • Użyj urządzenia zarządzanego przez Gradle: czy do testowania aplikacji używasz urządzeń zarządzanych przez Gradle.
  3. Kliknij Zakończ , aby utworzyć nowy moduł. Jeśli używasz kontroli źródła, może pojawić się prośba o dodanie nowo utworzonych plików modułu do kontroli źródła.

Definiowanie generatora profilu podstawowego

Nowo utworzony moduł zawiera testy, które służą do generowania i testowania porównawczego profilu podstawowego oraz do testowania tylko podstawowego uruchamiania aplikacji. Zalecamy rozszerzenie tych testów o najważniejsze ścieżki użytkownika i zaawansowane procesy uruchamiania. Upewnij się, że wszystkie testy związane z uruchamianiem aplikacji znajdują się w bloku rule z ustawioną wartością includeInStartupProfile na true. Z kolei, aby uzyskać optymalną wydajność, upewnij się, że wszystkie testy niezwiązane z uruchamianiem aplikacji nie są uwzględniane w profilu uruchamiania. Optymalizacje uruchamiania aplikacji służą do definiowania specjalnej części profilu podstawowego, zwanej profilem uruchamiania.

Aby ułatwić utrzymanie, wyodrębnij te najważniejsze ścieżki użytkownika poza wygenerowany profil podstawowy i kod testu porównawczego, aby można było ich używać w obu przypadkach. Oznacza to, że zmiany w najważniejszych ścieżkach użytkownika są stosowane konsekwentnie.

Generowanie i instalowanie profilu podstawowego

Szablon modułu profilu podstawowego dodaje nową konfigurację uruchamiania do generowania profilu podstawowego. Jeśli używasz wariantów produktu, Android Studio tworzy wiele konfiguracji uruchamiania, dzięki czemu możesz generować osobne profile podstawowe dla każdego wariantu.

Konfiguracja uruchomienia Generowanie profilu podstawowego.
Rysunek 2. Uruchomienie tej konfiguracji generuje profil podstawowy.

Po zakończeniu konfiguracji uruchamiania Wygeneruj profil podstawowy wygenerowany profil podstawowy jest kopiowany do pliku w profilowanym module. src/variant/generated/baselineProfiles/baseline-prof.txt Opcje wariantu to rodzaj kompilacji do publikacji lub wariant kompilacji obejmujący rodzaj kompilacji do publikacji.

Wygenerowany profil podstawowy jest pierwotnie tworzony w katalogu build/outputs. Pełna ścieżka zależy od wariantu lub wersji profilowanej aplikacji oraz od tego, czy do profilowania używasz urządzenia zarządzanego przez Gradle czy podłączonego urządzenia. Jeśli używasz nazw używanych przez kod i konfiguracje kompilacji wygenerowane przez szablon, profil podstawowy jest tworzony w pliku build/outputs/managed_device_android_test_additional_output/nonminifiedrelease/pixel6Api31/BaselineProfileGenerator_generate-baseline-prof.txt. Prawdopodobnie nie będziesz musiał bezpośrednio wchodzić w interakcję z tą wersją wygenerowanego profilu podstawowego, chyba że ręcznie kopiujesz go do modułów docelowych (niezalecane).

Tworzenie nowego profilu podstawowego za pomocą AGP 8.1

Jeśli nie możesz użyć szablonu modułu profilu podstawowego, użyj szablonu modułu Macrobenchmark i wtyczki Gradle profilu podstawowego, aby utworzyć nowy profil podstawowy. Zalecamy używanie tych narzędzi od wersji Android Studio Giraffe i AGP 8.1.

Oto kroki tworzenia nowego profilu podstawowego za pomocą szablonu modułu Macrobenchmark i wtyczki Gradle profilu podstawowego:

  1. Skonfiguruj moduł Macrobenchmark w projekcie Gradle.
  2. Zdefiniuj nową klasę o nazwie BaselineProfileGenerator:

    class BaselineProfileGenerator {
        @get:Rule
        val baselineProfileRule = BaselineProfileRule()
    
        @Test
        fun startup() = baselineProfileRule.collect(
            packageName = "com.example.app",
            profileBlock = {
                startActivityAndWait()
            }
        )
    }
    

    Generator może zawierać interakcje z aplikacją poza jej uruchamianiem. Dzięki temu możesz zoptymalizować wydajność aplikacji w czasie działania, np. przewijanie list, uruchamianie animacji i nawigowanie w obrębie Activity. Zobacz inne przykłady testów, które używają @BaselineProfileRule do ulepszania najważniejszych ścieżek użytkownika.

  3. Dodaj wtyczkę Gradle profilu podstawowego (libs.plugins.androidx.baselineprofile). Wtyczka ułatwia generowanie profili podstawowych i ich utrzymywanie w przyszłości.

  4. Aby wygenerować profil podstawowy, uruchom zadania Gradle :app:generateBaselineProfile lub :app:generateVariantBaselineProfile w terminalu.

    Uruchom generator jako test instrumentowany na urządzeniu fizycznym z rootem, emulatorze lub urządzeniu zarządzanym przez Gradle. Jeśli używasz urządzenia zarządzanego przez Gradle, ustaw aosp jako systemImageSource, ponieważ do generatora profilu podstawowego potrzebujesz dostępu do roota.

    Po zakończeniu zadania generowania profil podstawowy jest kopiowany do katalogu app/src//generated/baselineProfiles.

Tworzenie nowego profilu podstawowego bez szablonów

Zalecamy utworzenie profilu podstawowego za pomocą szablonu modułu profilu podstawowego w Android Studio Baseline Profile module template (preferowane) lub Macrobenchmark template, ale możesz też użyć samej wtyczki Gradle profilu podstawowego. Więcej informacji o wtyczce Gradle profilu podstawowego znajdziesz w artykule Konfigurowanie generowania profilu podstawowego.

Oto jak utworzyć profil podstawowy za pomocą wtyczki Gradle profilu podstawowego:

  1. Utwórz nowy moduł com.android.test, np. :baseline-profile.
  2. Skonfiguruj plik build.gradle.kts dla modułu :baseline-profile:

    1. Zastosuj wtyczkę androidx.baselineprofile.
    2. Upewnij się, że targetProjectPath wskazuje moduł :app.
    3. Opcjonalnie dodaj urządzenie zarządzane przez Gradle (GMD). W tym przykładzie jest to pixel6Api31. Jeśli nie zostanie określone, wtyczka używa podłączonego urządzenia, emulowanego lub fizycznego.
    4. Zastosuj wybraną konfigurację, jak pokazano w tym przykładzie.

    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
    }

    Dynamiczny

    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. Utwórz test profilu podstawowego w module testowym :baseline-profile. Ten przykład to test, który generuje profil podstawowy na potrzeby uruchamiania aplikacji.

        class BaselineProfileGenerator {
        @get:Rule
        val baselineProfileRule = BaselineProfileRule()
    
        @Test
        fun startup() = baselineProfileRule.collect(
            packageName = "com.example.app",
            profileBlock = {
                uiAutomator { startApp(PACKAGE_NAME) }
            }
        )
    }
    
  4. Zaktualizuj plik build.gradle.kts w module aplikacji, np. :app.

    1. Zastosuj wtyczkę androidx.baselineprofile.
    2. Dodaj zależność baselineProfile do modułu :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"))
    }

    Dynamiczny

    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. Wygeneruj profil, uruchamiając zadania Gradle :app:generateBaselineProfile lub :app:generateVariantBaselineProfile.

  6. Po zakończeniu zadania generowania profil podstawowy jest kopiowany do app/src/variant/generated/baselineProfiles.

Testowanie porównawcze profilu podstawowego

Aby przeprowadzić test porównawczy profilu podstawowego, utwórz nową konfigurację uruchamiania testu instrumentowanego na Androida za pomocą działania w rynnie, które wykonuje testy porównawcze zdefiniowane w pliku StartupBenchmarks.kt. Więcej informacji o testach porównawczych znajdziesz w artykułach Tworzenie klasy Macrobenchmark i Testowanie porównawcze profili podstawowych za pomocą biblioteki Macrobenchmark.

Rysunek 3. Uruchamianie testów na Androida za pomocą działania w rynnie action.

Gdy uruchomisz tę konfigurację w Android Studio, dane wyjściowe kompilacji będą zawierać szczegóły dotyczące wzrostu szybkości, jaki zapewnia profil podstawowy:

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

Przechwytywanie wszystkich wymaganych ścieżek kodu

Dwa kluczowe wskaźniki do pomiaru czasu uruchamiania aplikacji to:

TTFD jest zgłaszany po wywołaniu metody reportFullyDrawn klasy ComponentActivity. Jeśli metoda reportFullyDrawn nie zostanie nigdy wywołana, zamiast niej zostanie zgłoszony TTID. Może być konieczne opóźnienie wywołania metody reportFullyDrawn do momentu zakończenia wczytywania asynchronicznego. Jeśli na przykład interfejs zawiera dynamiczną listę leniwą, lista może być wypełniana przez zadanie w tle , które kończy się po pierwszym narysowaniu listy, a tym samym po oznaczeniu interfejsu jako w pełni narysowanego. W takich przypadkach kod, który jest uruchamiany po osiągnięciu przez interfejs stanu pełnego narysowania, nie jest uwzględniany w profilu podstawowym.

Aby uwzględnić wypełnianie listy w profilu podstawowym, pobierz FullyDrawnReporter za pomocą getFullyDrawnReporter i dodaj do niego reportera w kodzie aplikacji. Zwolnij reportera, gdy zadanie w tle zakończy wypełnianie listy. Metoda FullyDrawnReporter nie wywołuje metody reportFullyDrawn, dopóki nie zostaną zwolnieni wszyscy reporterzy. Dzięki temu profil podstawowy zawiera ścieżki kodu wymagane do wypełnienia listy. Nie zmienia to zachowania aplikacji dla użytkownika, ale pozwala profilowi podstawowemu uwzględnić wszystkie niezbędne ścieżki kodu.

Aby wskazać stan pełnego narysowania, użyj tych interfejsów API Compose:

  • ReportDrawn wskazuje, że element kompozycyjny jest natychmiast gotowy do interakcji.
  • ReportDrawnWhen przyjmuje predykat, np. list.count > 0, aby wskazać, kiedy element kompozycyjny jest gotowy do interakcji.
  • ReportDrawnAfter przyjmuje metodę zawieszającą, która po zakończeniu wskazuje, że element kompozycyjny jest gotowy do interakcji.