Tworzenie profili podstawowych

Automatycznie generuj profile dla każdej wersji aplikacji za pomocą biblioteki Jetpack Macrobenchmark i BaselineProfileRule. Podczas używania profili bazowych zalecamy użycie wersji com.android.tools.build:gradle:8.0.0 lub nowszej, która zwiększa możliwości kompilacji.

Oto ogólne kroki umożliwiające utworzenie nowego profilu podstawowego:

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

Po wygenerowaniu profilu podstawowego porównaj go na urządzeniu fizycznym, aby zmierzyć poprawę szybkości.

Utwórz nowy profil podstawowy z AGP 8.2 lub nowszym

Najłatwiejszym sposobem utworzenia nowego profilu podstawowego jest skorzystanie z szablonu modułu profilu podstawowego dostępnego w Android Studio Iguana i Android Gradle Plugin (AGP) 8.2.

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

Konfigurowanie modułu profilu podstawowego

Aby uruchomić szablon modułu profilu podstawowego, wykonaj następujące czynności:

  1. Wybierz File > New > New Module (Plik > Nowy moduł > Nowy moduł).
  2. W panelu Templates (Szablony) wybierz szablon Baseline Profile Generator i skonfiguruj go:
    Rysunek 1. Szablon modułu generatora profili podstawowych.

    Pola w szablonie są takie:

    • Docelowa aplikacja: określa aplikację, dla której generowany jest profil podstawowy. Jeśli w projekcie masz tylko 1 moduł aplikacji, na tej liście będzie widoczny tylko 1 element.
    • Nazwa modułu: nazwa, którą chcesz utworzyć dla tworzonego modułu profilu podstawowego.
    • Nazwa pakietu: nazwa pakietu, którą chcesz umieścić w module profilu podstawowego.
    • Language (Język): określa, czy chcesz wygenerować wygenerowany kod w języku Kotlin czy w Javie.
    • Język konfiguracji kompilacji: określa, czy w skryptach konfiguracji kompilacji chcesz używać skryptu Kotlin (KTS) czy Groovy.
    • Używaj urządzenia zarządzanego przez Gradle: niezależnie od tego, czy do testowania aplikacji używasz urządzeń zarządzanych przez Gradle.
  3. Kliknij Zakończ. Nowy moduł zostanie utworzony. 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.

Zdefiniuj generator profili podstawowych

Nowo utworzony moduł zawiera testy służące do generowania i porównywania profilu podstawowego oraz testowania tylko podstawowego uruchamiania aplikacji. Zalecamy ich uzupełnienie w ramach głównych przepływów pracy i zaawansowanych przepływów pracy przy uruchamianiu. Upewnij się, że wszystkie testy związane z uruchamianiem aplikacji znajdują się w bloku rule, a includeInStartupProfile ma wartość true. Aby uzyskać optymalną wydajność, dopilnuj, aby w profilu startowym nie były uwzględnione żadne testy niezwiązane z uruchamianiem aplikacji. Optymalizacje podczas uruchamiania aplikacji służą do definiowania specjalnej części profilu podstawowego nazywanego profilem startowym.

Ułatwia to utrzymanie, jeśli wyodrębnisz te główne interfejsy API poza wygenerowanym profilem bazowym i kodem porównawczym, aby można było ich używać w obu przypadkach. Oznacza to, że zmiany w głównych aplikacjach są wykorzystywane w spójny sposób.

Wygeneruj i zainstaluj profil podstawowy

Szablon modułu profilu podstawowego dodaje nową konfigurację uruchomienia w celu wygenerowania profilu podstawowego. Jeśli korzystasz z rodzajów usług, Android Studio tworzy konfiguracje wielu uruchomień, co pozwoli Ci wygenerować osobne profile bazowe dla każdego rodzaju.

Konfiguracja uruchomienia Generowanie profilu podstawowego.
Rysunek 2. Uruchomienie tej konfiguracji spowoduje wygenerowanie profilu podstawowego.

Po zakończeniu konfiguracji uruchamiania Wygeneruj profil podstawowy wygenerowany profil podstawowy zostanie skopiowany do pliku src/variant/generated/baselineProfiles/baseline-prof.txt w module, który jest profilowany. Opcje wariantu to albo typ kompilacji do publikacji, albo wariant kompilacji obejmujący typ kompilacji wersji.

Wygenerowany profil podstawowy został pierwotnie utworzony w build/outputs. Pełna ścieżka jest zależna od wariantu lub smaku profilowanej aplikacji oraz tego, czy do profilowania używasz urządzenia zarządzanego przez Gradle czy połączonego urządzenia. Jeśli używasz nazw używanych przez kod i konfiguracji kompilacji wygenerowanych przez szablon, profil podstawowy zostanie utworzony w pliku build/outputs/managed_device_android_test_additional_output/nonminifiedrelease/pixel6Api31/BaselineProfileGenerator_generate-baseline-prof.txt. Najprawdopodobniej nie będziesz mieć konieczności bezpośredniej interakcji z tą wersją wygenerowanego profilu podstawowego, chyba że ręcznie skopiujesz ją do modułów docelowych (niezalecane).

Utwórz nowy profil podstawowy z 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 korzystanie z tych narzędzi, zaczynając od Android Studio Giraffe i AGP 8.1.

Aby utworzyć nowy profil podstawowy za pomocą szablonu modułu Macrobenchmark i wtyczki Gradle profilu podstawowego:

  1. Skonfiguruj moduł analizy porównawczej makr 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 uruchomieniem. Pozwala to zoptymalizować wydajność aplikacji w środowisku wykonawczym, np. przewijanie list, uruchamianie animacji i poruszanie się po Activity. Zobacz inne przykłady testów, które wykorzystują @BaselineProfileRule do ulepszania najważniejszych ścieżek użytkowników.

  3. Dodaj wtyczkę Gradle profilu Baseline (libs.plugins.androidx.baselineprofile). Ułatwia ona generowanie profili bazowych i utrzymywanie ich w przyszłości.

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

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

    Na końcu zadania generowania profil podstawowy jest kopiowany do app/src/variant/generated/baselineProfiles.

Utwórz nowy profil podstawowy bez szablonów

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

Oto jak bezpośrednio utworzyć profil podstawowy za pomocą wtyczki Gradle profilu Baseline:

  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 poniższym przykładzie jest to pixel6Api31. Jeśli go nie podasz, będzie ona używać podłączonego urządzenia – emulowanego lub fizycznego.
    4. Zastosuj wybraną konfigurację, tak jak 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
    }
    

    Odlotowy

    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 uruchamia aplikację i czeka na bezczynność.

    Kotlin

    class BaselineProfileGenerator {
    
        @get:Rule
        val baselineRule = BaselineProfileRule()
    
        @Test
        fun startupBaselineProfile() {
            baselineRule.collect("com.myapp") {
                startActivityAndWait()
            }
        }
    }
    

    Java

    public class BaselineProfileGenerator {
    
        @Rule
        Public BaselineProfileRule baselineRule = new BaselineProfileRule();
    
        @Test
        Public void startupBaselineProfile() {
            baselineRule.collect(
                "com.myapp",
                (scope -> {
                    scope.startActivityAndWait();
                    Return Unit.INSTANCE;
                })
            )
        }
    }
    
  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"))
    }
    

    Odlotowy

    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 :app:generateBaselineProfile lub :app:generateVariantBaselineProfile Gradle.

  6. Na końcu zadania generowania profil podstawowy jest kopiowany do app/src/variant/generated/baselineProfiles.

Utwórz nowy profil podstawowy z AGP 7.3-7.4

Istnieje możliwość generowania profili podstawowych w wersji 7.3–7.4, ale zdecydowanie zalecamy uaktualnienie oprogramowania do wersji co najmniej 8.1, aby można było korzystać z wtyczki Gradle do profilu podstawowego i jej najnowszych funkcji.

Jeśli musisz utworzyć profile podstawowe w wersji 7.3–7.4, wykonaj te same czynności co w przypadku AGP 8.1 z tymi wyjątkami:

Ręczne stosowanie wygenerowanych reguł

Generator profili bazowych tworzy na urządzeniu plik tekstowy HRF (ang. Human Readable Format) i kopiuje go na hosta. Aby zastosować wygenerowany profil w kodzie, wykonaj te czynności:

  1. Znajdź plik HRF w folderze kompilacji modułu, w którym generujesz profil: [module]/build/outputs/managed_device_android_test_additional_output/[device].

    Profile są zgodne z [class name]-[test method name]-baseline-prof.txt wzorcem nazewnictwa, który wygląda tak: BaselineProfileGenerator-startup-baseline-prof.txt.

  2. Skopiuj wygenerowany profil do usługi src/main/ i zmień nazwę pliku na baseline-prof.txt.

  3. Dodaj zależność do biblioteki ProfileInstaller w pliku build.gradle.kts aplikacji, aby umożliwić lokalną kompilację profilu podstawowego, gdy profile Cloud są niedostępne. Jest to jedyny sposób lokalnego wczytywania profilu podstawowego z innych źródeł.

    dependencies {
         implementation("androidx.profileinstaller:profileinstaller:1.3.1")
    }
    
  4. Utwórz wersję produkcyjną aplikacji, a zastosowane reguły HRF zostaną skompilowane do postaci binarnej i załączone do pliku APK lub pakietu AAB. Następnie rozpowszechnij aplikację w zwykły sposób.

Przetestuj profil bazowy

Aby przeprowadzić analizę porównawczą profilu podstawowego, utwórz nową konfigurację ustanawianych testów na Androida na podstawie działania rynku, które wykonuje testy porównawcze zdefiniowane w pliku StartupBenchmarks.kt lub StartupBencharks.java. Więcej informacji o testach porównawczych znajdziesz w sekcjach Tworzenie klasy analizy porównawczej makr i automatyzowanie pomiarów za pomocą biblioteki Makroporównania.

Rysunek 3. Uruchamiaj testy Androida z działania rynku.

Gdy uruchomisz to w Android Studio, dane wyjściowe kompilacji będą zawierać szczegółowe informacje o przyspieszeniach, które 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

Przechwytuj wszystkie wymagane ścieżki kodu

Oto 2 kluczowe dane do pomiaru czasu uruchamiania aplikacji:

Czas do początkowego wyświetlenia (TTID)
Czas potrzebny na wyświetlenie pierwszej klatki interfejsu aplikacji.
Czas do pełnego wyświetlenia (TTFD)
TTID plus czas wyświetlania treści ładowanej asynchronicznie po wyświetleniu początkowej klatki.

TTFD jest zgłaszane po wywołaniu metody reportFullyDrawn() w ComponentActivity. Jeśli funkcja reportFullyDrawn() nigdy nie zostanie wywołana, zamiast tego raportowany jest TTID. Być może trzeba będzie opóźnić wywołanie metody reportFullyDrawn() do momentu zakończenia wczytywania asynchronicznego. Jeśli na przykład interfejs zawiera listę dynamiczną, taką jak RecyclerView czy leniwa lista, może ona być wypełniana przez zadanie w tle, które kończy się po jej pierwszym narysowaniu – czyli wtedy, gdy interfejs zostanie oznaczony jako w pełni narysowany. W takich przypadkach kod, który uruchamia się, gdy interfejs użytkownika osiągnie pełną wersję, nie jest uwzględniany w profilu bazowym.

Aby w profilu bazowym uwzględnić wypełnianie listy, pobierz funkcję FullyDrawnReporter za pomocą parametru getFullyDrawnReporter() i dodaj do niej reportera w kodzie aplikacji. Zwolnij, gdy zadanie w tle zakończy zapełnianie listy. FullyDrawnReporter wywołuje metodę reportFullyDrawn() dopiero wtedy, gdy zostaną zwolnieni wszyscy zgłaszający. Dzięki temu profil podstawowy będzie zawierał ścieżki kodu wymagane do wypełnienia listy. Nie ma to wpływu na zachowanie aplikacji względem użytkownika, ale umożliwia dołączenie do profilu podstawowego wszystkich niezbędnych ścieżek kodu.

Jeśli Twoja aplikacja używa funkcji Jetpack Compose, w celu wskazania jej stanu w pełni użyj tych interfejsów API:

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