Tworzenie profili podstawowych

Profile podstawowe są niezbędne do maksymalizacji wydajności Jetpack Compose. Wstępna kompilacja głównych ś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. Zalecamy używanie wersji com.android.tools.build:gradle:8.0.0 lub nowszej, aby korzystać z ulepszeń kompilacji podczas używania profili Baseline.

Oto ogólne instrukcje tworzenia nowego profilu Baseline:

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

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

Tworzenie nowego profilu podstawowego za pomocą AGP 8.2 lub nowszego

Najprostszym sposobem na utworzenie nowego profilu Baseline jest użycie szablonu modułu profilu Baseline, 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 Baseline w Android Studio automatyzuje tworzenie nowego modułu do generowania i testowania profili Baseline. Uruchomienie szablonu generuje większość typowej konfiguracji kompilacji, generowania profilu Baseline i kodu weryfikacyjnego. Szablon tworzy kod do generowania i testowania profili podstawowych w celu pomiaru uruchamiania aplikacji.

Konfigurowanie modułu profilu podstawowego

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

  1. Wybierz File > New > New Module (Plik > Nowy > Nowy moduł).
  2. Wybierz szablon Baseline Profile Generator (Generator profilu podstawowego) w panelu Templates (Szablony) i skonfiguruj go:
    Rysunek 1. Szablon modułu generatora profilu podstawowego.
    Szablon zawiera te pola:
    • 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 tworzonego modułu profilu Baseline.
    • Nazwa pakietu: nazwa pakietu, którą chcesz nadać modułowi profilu Baseline.
    • Language (Język): wybierz, czy wygenerowany kod ma być w języku Kotlin czy Java.
    • Język konfiguracji kompilacji: czy chcesz używać skryptu Kotlin (KTS) czy Groovy w skryptach konfiguracji kompilacji.
    • Używaj 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 generują i testują profil Baseline, oraz testy, które sprawdzają tylko podstawowe uruchamianie aplikacji. Zalecamy rozszerzenie ich o CUJ i zaawansowane przepływy pracy związane z uruchamianiem. Upewnij się, że wszystkie testy związane z uruchamianiem aplikacji znajdują się w bloku rule z atrybutem includeInStartupProfile ustawionym na true. Z kolei aby uzyskać optymalną wydajność, upewnij się, że wszystkie testy niezwiązane z uruchamianiem aplikacji nie są uwzględnione w profilu uruchamiania. Optymalizacje uruchamiania aplikacji służą do definiowania specjalnej części profilu Baseline, która nazywa się profilem uruchamiania.

Aby ułatwić konserwację, warto wyodrębnić te CUJ 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 CUJ są stosowane spójnie.

Generowanie i instalowanie profilu podstawowego

Szablon modułu profilu podstawowego dodaje nową konfigurację uruchamiania, która umożliwia wygenerowanie profilu podstawowego. Jeśli używasz wariantów usługi, Android Studio tworzy wiele konfiguracji uruchamiania, dzięki czemu możesz wygenerować osobne profile Baseline dla każdego wariantu.

Konfiguracja uruchamiania generowania profilu Baseline.
Rysunek 2. Uruchomienie tej konfiguracji spowoduje wygenerowanie profilu Baseline.

Po zakończeniu konfiguracji uruchamiania Generate Baseline Profile wygenerowany profil Baseline Profile jest kopiowany do pliku src/variant/generated/baselineProfiles/baseline-prof.txt w profilowanym module. Opcje wariantów to typ kompilacji do publikacji lub wariant kompilacji obejmujący typ kompilacji do publikacji.

Wygenerowany profil podstawowy jest pierwotnie tworzony w 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 połączonego urządzenia. Jeśli użyjesz nazw używanych przez konfiguracje kodu i kompilacji wygenerowane przez szablon, profil Baseline zostanie utworzony w pliku build/outputs/managed_device_android_test_additional_output/nonminifiedrelease/pixel6Api31/BaselineProfileGenerator_generate-baseline-prof.txt. Prawdopodobnie nie będziesz musiał bezpośrednio korzystać z tej wersji wygenerowanego profilu Baseline, chyba że ręcznie skopiujesz 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, utwórz nowy profil podstawowy za pomocą szablonu modułu Macrobenchmark i wtyczki Baseline Profile do Gradle. Zalecamy korzystanie z tych narzędzi, zaczynając od Android Studio Giraffe i wtyczki Androida do obsługi Gradle 8.1.

Aby utworzyć nowy profil podstawowy za pomocą szablonu modułu Macrobenchmark i wtyczki Baseline Profile do Gradle:

  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ą wykraczające poza jej uruchomienie. Dzięki temu możesz zoptymalizować wydajność aplikacji w czasie działania, np. przewijanie list, odtwarzanie animacji i poruszanie się po Activity. Zobacz inne przykłady testów, które wykorzystują @BaselineProfileRule do ulepszania głównych ścieżek użytkownika.

  3. Dodaj wtyczkę Baseline Profile Gradle (libs.plugins.androidx.baselineprofile). Ułatwia ona generowanie profili Baseline i zarządzanie nimi w przyszłości.

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

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

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

Tworzenie nowego profilu podstawowego bez szablonów

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

Aby utworzyć profil podstawowy bezpośrednio za pomocą wtyczki Baseline Profile do Gradle:

  1. Utwórz nowy moduł com.android.test, np. :baseline-profile.
  2. Skonfiguruj plik build.gradle.kts dla :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żyje połączonego urządzenia, emulowanego lub fizycznego.
    4. Zastosuj odpowiednią konfigurację, jak w poniższym 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. Poniższy 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 Baseline jest kopiowany do app/src/variant/generated/baselineProfiles.

Test porównawczy profilu podstawowego

Aby przeprowadzić test porównawczy profilu Baseline, utwórz nową konfigurację uruchamiania testu instrumentowanego na Androidzie, korzystając z działania na marginesie, 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 Testy porównawcze profili podstawowych z użyciem biblioteki Macrobenchmark.

Rysunek 3. Uruchom testy Androida z poziomu rynny.

Gdy uruchomisz to w Android Studio, dane wyjściowe kompilacji będą zawierać szczegółowe informacje o poprawie szybkości, którą zapewnia profil Baseline:

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

Uwzględnij wszystkie wymagane ścieżki kodu

Oto 2 główne dane służące do pomiaru czasu uruchamiania aplikacji:

TTFD jest raportowany po wywołaniu metody reportFullyDrawn klasy ComponentActivity. Jeśli funkcja reportFullyDrawn nie zostanie wywołana, zamiast tego zostanie zgłoszony TTID. Może być konieczne opóźnienie wywołania funkcji reportFullyDrawn do momentu zakończenia asynchronicznego wczytywania. Jeśli na przykład interfejs zawiera dynamiczną listę leniwą, może ona zostać wypełniona przez zadanie w tle, które kończy się po pierwszym narysowaniu listy, a więc 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 Baseline.

Aby uwzględnić wypełnianie listy w profilu podstawowym, pobierz FullyDrawnReporter za pomocą getFullyDrawnReporter i dodaj do niego reportera w kodzie aplikacji. Zwolnij reportera po zakończeniu wypełniania listy przez zadanie w tle. FullyDrawnReporter nie wywołuje metody reportFullyDrawn, dopóki nie zostaną zwolnione wszystkie obiekty reporter. Dzięki temu profil Baseline zawiera ścieżki kodu wymagane do wypełnienia listy. Nie zmienia to działania aplikacji dla użytkownika, ale pozwala profilowi Baseline uwzględnić wszystkie niezbędne ścieżki kodu.

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

  • ReportDrawn wskazuje, że funkcja kompozycyjna jest natychmiast gotowa do interakcji.
  • ReportDrawnWhen przyjmuje predykat, np. list.count > 0, aby wskazać, kiedy funkcja kompozycyjna jest gotowa do interakcji.
  • ReportDrawnAfter przyjmuje metodę zawieszenia, która po zakończeniu wskazuje, że funkcja kompozycyjna jest gotowa do interakcji.