Tworzenie profili podstawowych

Automatyczne generowanie profili dla każdej wersji aplikacji za pomocą biblioteki Macrobenchmark JetpackaBaselineProfileRule. Zalecamy używanie wersji com.android.tools.build:gradle:8.0.0 lub nowszej, która zawiera ulepszenia kompilacji przy użyciu profili referencyjnych.

Oto ogólne instrukcje tworzenia nowego profilu bazowego:

  1. Skonfiguruj moduł Profil podstawowy.
  2. Zdefiniuj test JUnit, który pomoże wygenerować profile referencyjne.
  3. Dodaj główne ścieżki użytkownika, które chcesz zoptymalizować.
  4. Wygeneruj profil podstawowy.

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

Tworzenie nowego profilu referencyjnego za pomocą AGP 8.2 lub nowszej wersji

Najprostszym sposobem utworzenia nowego profilu bazowego jest użycie szablonu modułu profilu bazowego, który jest dostępny od wersji Android Studio Iguana i Android Gradle Plugin (AGP) 8.2.

Szablon modułu Generatora profili referencyjnych w Android Studio automatyzuje tworzenie nowego modułu służącego do generowania i porównywania profili referencyjnych. Uruchomienie szablonu powoduje wygenerowanie większości typowej konfiguracji, profilu bazowego i kodu weryfikacyjnego. Szablon tworzy kod do generowania i porównywania profili podstawowych, aby mierzyć czas uruchamiania aplikacji.

Konfigurowanie modułu profilu podstawowego

Aby uruchomić szablon modułu Profil bazowy:

  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:

    • Docelowa aplikacja: określa, dla której aplikacji ma być generowany profil podstawowy. Jeśli w projekcie jest tylko 1 moduł aplikacji, na tej liście znajduje się tylko 1 element.
    • Nazwa modułu: nazwa tworzonego modułu profilu podstawowego.
    • Nazwa pakietu: nazwa pakietu, którą chcesz przypisać do modułu profilu podstawowego.
    • Język: określ, czy wygenerowany kod ma być w języku Kotlin czy Java.
    • Język konfiguracji kompilacji: określ, czy chcesz używać skryptów konfiguracji kompilacji w języku Kotlin Script (KTS) czy Groovy.
    • Używanie urządzenia zarządzanego przez Gradle: określ, czy chcesz używać urządzeń zarządzanych przez Gradle do testowania aplikacji.
  3. Kliknij Gotowe, aby utworzyć nowy moduł. Jeśli korzystasz z kontroli źródła, możesz zobaczyć prośbę o dodanie nowo utworzonych plików modułów do kontroli źródła.

Definiowanie generatora profilu podstawowego

Nowo utworzony moduł zawiera testy służące do generowania i porównywania profilu bazowego oraz testowania tylko podstawowego uruchamiania aplikacji. Zalecamy rozszerzenie tych procesów o procesy związane z zapytaniami o udzielenie zgody użytkownika i zaawansowane procesy uruchamiania. Upewnij się, że wszystkie testy związane z uruchamianiem aplikacji znajdują się w bloku rule, a wartość parametru includeInStartupProfile jest ustawiona na true. Z kolei, aby zapewnić optymalną wydajność, sprawdź, czy testy niezwiązane z uruchamianiem aplikacji nie są uwzględnione w profilu uruchamiania. Optymalizacje uruchamiania aplikacji służą do definiowania specjalnej części profilu bazowego o nazwie profil uruchamiania.

Aby ułatwić utrzymanie, warto wyodrębnić te dane z wygenerowanego profilu podstawowego i kodu testu porównawczego, aby można było ich używać w obu przypadkach. Oznacza to, że zmiany w CUJ są konsekwentnie stosowane.

Generowanie i instalowanie profilu podstawowego

Szablon modułu profilu podstawowego dodaje nową konfigurację uruchomienia, aby wygenerować profil podstawowy. Jeśli używasz wersji produktu, Android Studio tworzy wiele konfiguracji uruchomienia, aby umożliwić generowanie oddzielnych profili referencyjnych dla każdej wersji.

Konfiguracja uruchomienia generowania profilu podstawowego.
Rysunek 2. Uruchomienie tej konfiguracji powoduje wygenerowanie profilu bazowego.

Po zakończeniu konfiguracji uruchomienia Generowanie profilu podstawowego wygenerowany profil podstawowy zostanie skopiowany do pliku src/variant/generated/baselineProfiles/baseline-prof.txt w module, który jest profilowany. Opcje wariantów to typ kompilacji wersji lub wariant kompilacji, który wykorzystuje typ kompilacji wersji.

Wygenerowany profil podstawowy został pierwotnie utworzony w build/outputs. Pełna ścieżka zależy od wariantu lub wersji aplikacji, której profil jest tworzony, oraz od 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 konfiguracje kompilacji wygenerowane przez szablon, profil bazowy 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 podstawowego, chyba że będziesz go kopiować ręcznie do modułów docelowych (nie zalecane).

Tworzenie nowego profilu referencyjnego za pomocą AGP 8.1

Jeśli nie możesz użyć szablonu modułu profilu referencyjnego, użyj szablonu modułu makrobenchmarku i wtyczki Gradle do profilu referencyjnego, aby utworzyć nowy profil referencyjny. Zalecamy korzystanie z tych narzędzi od wersji Android Studio Giraffe i AGP 8.1.

Oto instrukcje tworzenia nowego profilu referencyjnego za pomocą szablonu modułu Macrobenchmark i wtyczki Gradle do profilu referencyjnego:

  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 Twoją aplikacją poza jej uruchamianiem. Dzięki temu możesz optymalizować wydajność aplikacji w czasie działania, np. przewijanie list, uruchamianie animacji i przemieszczanie się w aplikacji.Activity Zobacz inne przykłady testów, które korzystają z funkcji @BaselineProfileRule, aby poprawić najważniejsze ścieżki użytkowników.

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

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

    Uruchom generator jako test z instrumentacją na urządzeniu fizycznym z rootem, w emulatorze lub na urządzeniu zarządzanym przez Gradle. Jeśli używasz urządzenia zarządzanego przez Gradle, jako aosp ustaw systemImageSource, ponieważ do generatora profilu podstawowego potrzebny jest dostęp root.

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

Tworzenie nowego profilu podstawowego bez szablonów

Zalecamy utworzenie profilu bazowego za pomocą szablonu modułu profilu bazowego w Android Studio (zalecane) lub szablonu Macrobenchmark, ale możesz też użyć samego wtyczki Gradle do profilu bazowego. Więcej informacji o wtyczce Gradle do generowania profilu podstawowego znajdziesz w artykule Konfigurowanie generowania profilu podstawowego.

Oto jak utworzyć profil bazowy, korzystając bezpośrednio z wtyczki Gradle do tworzenia profili bazowych:

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

    1. Zastosuj wtyczkę androidx.baselineprofile.
    2. Upewnij się, że targetProjectPath wskazuje na moduł :app.
    3. Opcjonalnie dodaj urządzenie zarządzane przez Gradle (GMD). W tym przykładzie jest to pixel6Api31. Jeśli nie jest to 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
    }

    Groovy

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

    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 do modułu :baseline-profile zależność baselineProfile.

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

    Groovy

    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, wykonując zadania :app:generateBaselineProfilelub :app:generateVariantBaselineProfile w Gradle.

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

Tworzenie nowego profilu bazowego za pomocą AGP 7.3–7.4

Profile bazowe można generować za pomocą AGP 7.3–7.4, ale zdecydowanie zalecamy przejście na co najmniej AGP 8.1, aby móc korzystać z wtyczki Gradle do tworzenia profili bazowych i jego najnowszych funkcji.

Jeśli musisz utworzyć profile bazowe za pomocą AGP 7.3–7.4, musisz wykonać te same czynności, co w przypadku AGP 8.1, z tymi wyjątkami:

Ręczne stosowanie wygenerowanych reguł

Generator profilu bazowego tworzy na urządzeniu plik tekstowy w formacie HRF i kopiuje go na komputer hosta. Aby zastosować wygenerowany profil do kodu:

  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 ze wzorcem nazewnictwa [class name]-[test method name]-baseline-prof.txt, który wygląda tak: BaselineProfileGenerator-startup-baseline-prof.txt.

  2. Skopiuj wygenerowany profil do folderu src/main/ i nazwij plik 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 w chmurze są niedostępne. Jest to jedyny sposób na lokalne zainstalowanie profilu podstawowego.

    dependencies {
         implementation("androidx.profileinstaller:profileinstaller:1.4.1")
    }
    
  4. Skompiluj wersję produkcyjną aplikacji, gdy zastosowane zasady HRF są skompilowane w postaci binarnej i zawarto je w pliku APK lub AAB. Następnie rozpowszechnij aplikację w zwykły sposób.

Porównywanie profilu podstawowego

Aby przeprowadzić test porównawczy profilu bazowego, utwórz nową konfigurację testu z wykorzystaniem pomiarów z Androida na podstawie działania w rynnie, które wykonuje testy porównawcze zdefiniowane w pliku StartupBenchmarks.kt lub StartupBencharks.java. Więcej informacji o testowaniu porównawczym znajdziesz w artykułach Tworzenie klasy MacrobenchmarkAutomatyzacja pomiarów za pomocą biblioteki Macrobenchmark.

Rysunek 3. Uruchom testy Androida z poziomu ścieżki.

Gdy uruchomisz to w Android Studio, dane wyjściowe kompilacji będą zawierać szczegóły dotyczące ulepszeń szybkości, 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

Uwzględnij wszystkie wymagane ścieżki kodu

Oto 2 kluczowe wskaźniki pomiaru czasu uruchamiania aplikacji:

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

TTFD jest zgłaszany, gdy wywoływana jest metoda reportFullyDrawn() metody ComponentActivity. Jeśli funkcja reportFullyDrawn() nigdy nie zostanie wywołana, zamiast niej zostanie zgłoszony identyfikator TTID. Może być konieczne opóźnienie wywołania funkcji reportFullyDrawn() do czasu zakończenia wczytywania asynchronicznego. Jeśli na przykład interfejs zawiera listę dynamiczną, taką jak RecyclerView lub lazylist, może ona być wypełniana przez zadanie w tle, które jest wykonywane po pierwszym narysowaniu listy, a zatem po tym, jak interfejs został oznaczony jako w pełni narysowany. W takich przypadkach kod, który jest wykonywany po osiągnięciu przez interfejs stanu pełnego narysowania, nie jest uwzględniany w profilu bazowym.

Aby uwzględnić populację listy w ramach profilu podstawowego, użyj funkcji FullyDrawnReporter, korzystając z funkcji getFullyDrawnReporter() i dodaj do niej reportera w kodzie aplikacji. Po zakończeniu wypełniania listy przez zadanie w tle zwróć do raportu. Funkcja FullyDrawnReporter nie wywołuje metody reportFullyDrawn(), dopóki wszyscy reporterzy nie zostaną zwolnieni. Dzięki temu profil bazowy zawiera ścieżki kodu wymagane do wypełnienia listy. Nie zmienia to działania aplikacji dla użytkownika, ale pozwala profilowi bazowemu uwzględnić wszystkie niezbędne ścieżki kodu.

Jeśli Twoja aplikacja korzysta z Jetpack Compose, użyj tych interfejsów API, aby wskazać stan pełnego wyświetlenia:

  • ReportDrawn wskazuje, że komponent jest od razu gotowy do interakcji.
  • ReportDrawnWhen odbiera predykat, np. list.count > 0, aby wskazać, kiedy kompozyt jest gotowy do interakcji.
  • ReportDrawnAfter zawiera metodę zawieszania, która po zakończeniu wskazuje, że kompozyt jest gotowy do interakcji.