Debugowanie profili podstawowych

W tym dokumencie znajdziesz sprawdzone metody i instrukcje rozwiązywania problemów, które pomogą Ci zdiagnozować problemy i upewnić się, że profile podstawowe działają prawidłowo i przynoszą jak największe korzyści.

Problemy z kompilacją

Jeśli skopiujesz przykład profili bazowych z aplikacji przykładowej Now in Android, podczas wykonywania zadania związanego z profilami bazowymi możesz napotkać błędy testów, które wskazują, że testów nie można uruchomić na emulatorze:

./gradlew assembleDemoRelease
Starting a Gradle Daemon (subsequent builds will be faster)
Calculating task graph as no configuration cache is available for tasks: assembleDemoRelease
Type-safe project accessors is an incubating feature.

> Task :benchmarks:pixel6Api33DemoNonMinifiedReleaseAndroidTest
Starting 14 tests on pixel6Api33

com.google.samples.apps.nowinandroid.foryou.ScrollForYouFeedBenchmark > scrollFeedCompilationNone[pixel6Api33] FAILED
        java.lang.AssertionError: ERRORS (not suppressed): EMULATOR
        WARNINGS (suppressed):
        ...

Błędy występują, ponieważ aplikacja Now in Android używa urządzenia zarządzanego przez Gradle do generowania profilu podstawowego. Błędy są oczekiwane, ponieważ zwykle nie należy uruchamiać testów wydajności na emulatorze. Jednak ponieważ podczas generowania profili podstawowych nie zbierasz danych o skuteczności, możesz dla wygody uruchamiać zbieranie profili podstawowych na emulatorach. Aby używać profili podstawowych z emulatorem, przeprowadź kompilację i instalację z poziomu wiersza poleceń i ustaw argument, aby włączyć reguły profili podstawowych:

installDemoRelease -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=BaselineProfile

Możesz też utworzyć niestandardową konfigurację uruchamiania w Android Studio, aby włączyć profile bazowe na emulatorach. W tym celu kliknij Uruchom > Edytuj konfiguracje:

Dodawanie niestandardowej konfiguracji uruchamiania w celu tworzenia profili podstawowych w aplikacji Now in Android
Rysunek 1. Dodaj niestandardową konfigurację uruchamiania, aby utworzyć profile Baseline w aplikacji Now in Android.

Sprawdzanie instalacji i stosowania profilu

Aby sprawdzić, czy sprawdzany plik APK lub pakiet Android App Bundle (AAB) pochodzi z wersji kompilacji, która zawiera profile bazowe:

  1. W Android Studio wybierz Build > Analyze APK (Utwórz > Przeanalizuj APK).
  2. Otwórz plik AAB lub APK.
  3. Sprawdź, czy plik baseline.prof istnieje:

    • Jeśli sprawdzasz plik AAB, profil znajduje się w lokalizacji /BUNDLE-METADATA/com.android.tools.build.profiles/baseline.prof.
    • Jeśli sprawdzasz plik APK, profil znajduje się w tym miejscu:/assets/dexopt/baseline.prof

      Obecność tego pliku jest pierwszym sygnałem prawidłowej konfiguracji kompilacji. Jeśli go nie ma, oznacza to, że środowisko wykonawcze Androida nie otrzyma żadnych instrukcji wstępnej kompilacji podczas instalacji.

      Sprawdzanie profilu podstawowego za pomocą narzędzia APK Analyzer w Android Studio
      Rysunek 2. Sprawdź profil podstawowy za pomocą narzędzia APK Analyzer w Android Studio.

Profile podstawowe muszą być kompilowane na urządzeniu, na którym działa aplikacja. Podczas instalowania wersji, których nie można debugować, za pomocą Android Studio lub narzędzia wiersza poleceń Gradle Wrapper kompilacja na urządzeniu odbywa się automatycznie. Jeśli zainstalujesz aplikację ze Sklepu Google Play, profile podstawowe zostaną skompilowane podczas aktualizacji urządzenia w tle, a nie w momencie instalacji. Gdy aplikacja jest instalowana za pomocą innych narzędzi, biblioteka Jetpack ProfileInstaller odpowiada za umieszczanie profili w kolejce do kompilacji podczas następnego procesu optymalizacji DEX w tle.

W takich przypadkach, jeśli chcesz mieć pewność, że używane są profile podstawowe, może być konieczne wymuszenie kompilacji profili podstawowych. ProfileVerifier umożliwia sprawdzanie stanu instalacji i kompilacji profilu, jak pokazano w tym przykładzie:

Kotlin

private const val TAG = "MainActivity"

class MainActivity : ComponentActivity() {
  ...
  override fun onResume() {
    super.onResume()
    lifecycleScope.launch {
      logCompilationStatus()
    }
  }

  private suspend fun logCompilationStatus() {
     withContext(Dispatchers.IO) {
        val status = ProfileVerifier.getCompilationStatusAsync().await()
        when (status.profileInstallResultCode) {
            RESULT_CODE_NO_PROFILE ->
                Log.d(TAG, "ProfileInstaller: Baseline Profile not found")
            RESULT_CODE_COMPILED_WITH_PROFILE ->
                Log.d(TAG, "ProfileInstaller: Compiled with profile")
            RESULT_CODE_PROFILE_ENQUEUED_FOR_COMPILATION ->
                Log.d(TAG, "ProfileInstaller: Enqueued for compilation")
            RESULT_CODE_COMPILED_WITH_PROFILE_NON_MATCHING ->
                Log.d(TAG, "ProfileInstaller: App was installed through Play store")
            RESULT_CODE_ERROR_PACKAGE_NAME_DOES_NOT_EXIST ->
                Log.d(TAG, "ProfileInstaller: PackageName not found")
            RESULT_CODE_ERROR_CACHE_FILE_EXISTS_BUT_CANNOT_BE_READ ->
                Log.d(TAG, "ProfileInstaller: Cache file exists but cannot be read")
            RESULT_CODE_ERROR_CANT_WRITE_PROFILE_VERIFICATION_RESULT_CACHE_FILE ->
                Log.d(TAG, "ProfileInstaller: Can't write cache file")
            RESULT_CODE_ERROR_UNSUPPORTED_API_VERSION ->
                Log.d(TAG, "ProfileInstaller: Enqueued for compilation")
            else ->
                Log.d(TAG, "ProfileInstaller: Profile not compiled or enqueued")
        }
    }
}

Java

public class MainActivity extends ComponentActivity {

    private static final String TAG = "MainActivity";

    @Override
    protected void onResume() {
        super.onResume();

        logCompilationStatus();
    }

    private void logCompilationStatus() {
         ListeningExecutorService service = MoreExecutors.listeningDecorator(
                Executors.newSingleThreadExecutor());
        ListenableFuture<ProfileVerifier.CompilationStatus> future =
                ProfileVerifier.getCompilationStatusAsync();
        Futures.addCallback(future, new FutureCallback<>() {
            @Override
            public void onSuccess(CompilationStatus result) {
                int resultCode = result.getProfileInstallResultCode();
                if (resultCode == RESULT_CODE_NO_PROFILE) {
                    Log.d(TAG, "ProfileInstaller: Baseline Profile not found");
                } else if (resultCode == RESULT_CODE_COMPILED_WITH_PROFILE) {
                    Log.d(TAG, "ProfileInstaller: Compiled with profile");
                } else if (resultCode == RESULT_CODE_PROFILE_ENQUEUED_FOR_COMPILATION) {
                    Log.d(TAG, "ProfileInstaller: Enqueued for compilation");
                } else if (resultCode == RESULT_CODE_COMPILED_WITH_PROFILE_NON_MATCHING) {
                    Log.d(TAG, "ProfileInstaller: App was installed through Play store");
                } else if (resultCode == RESULT_CODE_ERROR_PACKAGE_NAME_DOES_NOT_EXIST) {
                    Log.d(TAG, "ProfileInstaller: PackageName not found");
                } else if (resultCode == RESULT_CODE_ERROR_CACHE_FILE_EXISTS_BUT_CANNOT_BE_READ) {
                    Log.d(TAG, "ProfileInstaller: Cache file exists but cannot be read");
                } else if (resultCode
                        == RESULT_CODE_ERROR_CANT_WRITE_PROFILE_VERIFICATION_RESULT_CACHE_FILE) {
                    Log.d(TAG, "ProfileInstaller: Can't write cache file");
                } else if (resultCode == RESULT_CODE_ERROR_UNSUPPORTED_API_VERSION) {
                    Log.d(TAG, "ProfileInstaller: Enqueued for compilation");
                } else {
                    Log.d(TAG, "ProfileInstaller: Profile not compiled or enqueued");
                }
            }

            @Override
            public void onFailure(Throwable t) {
                Log.d(TAG,
                        "ProfileInstaller: Error getting installation status: " + t.getMessage());
            }
        }, service);
    }
}

Poniższe kody wyników zawierają wskazówki dotyczące przyczyn niektórych problemów:

RESULT_CODE_COMPILED_WITH_PROFILE
Profil jest instalowany i kompilowany, a potem używany przy każdym uruchomieniu aplikacji. To jest wynik, który chcesz zobaczyć.
RESULT_CODE_ERROR_NO_PROFILE_EMBEDDED
W uruchomionym pliku APK nie znaleziono profilu. Jeśli widzisz ten błąd, upewnij się, że używasz wersji kompilacji, która zawiera profile podstawowe, a plik APK zawiera profil.
RESULT_CODE_NO_PROFILE
Podczas instalowania aplikacji w sklepie z aplikacjami lub menedżerze pakietów nie zainstalowano profilu dla tej aplikacji. Główną przyczyną tego kodu błędu jest to, że instalator profilu nie został uruchomiony z powodu wyłączenia ProfileInstallerInitializer. Pamiętaj, że gdy ten błąd jest zgłaszany, w pliku APK aplikacji nadal znajduje się profil osadzony. Jeśli nie znaleziono osadzonego profilu, zwracany jest kod błędu RESULT_CODE_ERROR_NO_PROFILE_EMBEDDED.
RESULT_CODE_PROFILE_ENQUEUED_FOR_COMPILATION
Profil został znaleziony w pliku APK lub AAB i jest w kolejce do kompilacji. Gdy profil zostanie zainstalowany przez ProfileInstaller, jest on umieszczany w kolejce do kompilacji przy następnym uruchomieniu przez system optymalizacji DEX w tle. Profil nie jest aktywny, dopóki kompilacja nie zostanie ukończona. Nie próbuj przeprowadzać testów porównawczych profili podstawowych, dopóki kompilacja się nie zakończy. Może być konieczne wymuszenie kompilacji profili podstawowych. Ten błąd nie wystąpi, gdy aplikacja zostanie zainstalowana ze Sklepu Play lub menedżera pakietów na urządzeniach z Androidem 9 (API 28) lub nowszym, ponieważ kompilacja jest przeprowadzana podczas instalacji.
RESULT_CODE_COMPILED_WITH_PROFILE_NON_MATCHING
Zainstalowano niezgodny profil i aplikacja została z nim skompilowana. Jest to wynik instalacji ze Sklepu Google Play lub menedżera pakietów. Pamiętaj, że ten wynik różni się od RESULT_CODE_COMPILED_WITH_PROFILE, ponieważ niepasujący profil będzie zawierać tylko metody, które są nadal udostępniane między profilem a aplikacją. Profil jest w praktyce mniejszy niż oczekiwano, a metod będzie mniej niż w profilu bazowym.
RESULT_CODE_ERROR_CANT_WRITE_PROFILE_VERIFICATION_RESULT_CACHE_FILE
ProfileVerifier nie może zapisać pliku pamięci podręcznej z wynikami weryfikacji. Może to być spowodowane problemem z uprawnieniami do folderu aplikacji lub brakiem wolnego miejsca na dysku urządzenia.
RESULT_CODE_ERROR_UNSUPPORTED_API_VERSION
ProfileVerifieris running on an unsupported API version of Android. ProfileVerifier obsługuje tylko Androida 9 (poziom interfejsu API 28) i nowsze wersje.
RESULT_CODE_ERROR_PACKAGE_NAME_DOES_NOT_EXIST
Wyjątek PackageManager.NameNotFoundException jest zgłaszany podczas wysyłania zapytania do elementu PackageManager o pakiet aplikacji. Rzadko się to zdarza. Spróbuj odinstalować aplikację i ponownie zainstalować wszystko.
RESULT_CODE_ERROR_CACHE_FILE_EXISTS_BUT_CANNOT_BE_READ
Istnieje plik pamięci podręcznej z poprzednim wynikiem weryfikacji, ale nie można go odczytać. Rzadko się to zdarza. Spróbuj odinstalować aplikację i ponownie zainstalować wszystko.

Używanie ProfileVerifier w wersji produkcyjnej

W środowisku produkcyjnym możesz używać ProfileVerifier w połączeniu z bibliotekami raportowania analitycznego, takimi jak Google Analytics dla Firebase, aby generować zdarzenia analityczne wskazujące stan profilu. Na przykład ta funkcja szybko powiadamia, gdy zostanie wydana nowa wersja aplikacji, która nie zawiera profili podstawowych.

Wymuszanie kompilacji profili podstawowych

Jeśli stan kompilacji profili podstawowych to RESULT_CODE_PROFILE_ENQUEUED_FOR_COMPILATION, możesz wymusić natychmiastową kompilację za pomocą tego polecenia: adb

adb shell cmd package compile -r bg-dexopt PACKAGE_NAME

Sprawdzanie stanu kompilacji profilu podstawowego bez ProfileVerifier

Jeśli nie używasz ProfileVerifier, możesz sprawdzić stan kompilacji za pomocą adb, ale nie daje on tak szczegółowych informacji jak ProfileVerifier:

adb shell dumpsys package dexopt | grep -A 2 PACKAGE_NAME

Użycie adb daje wynik podobny do tego:

  [com.google.samples.apps.nowinandroid.demo]
    path: /data/app/~~dzJiGMKvp22vi2SsvfjkrQ==/com.google.samples.apps.nowinandroid.demo-7FR1sdJ8ZTy7eCLwAnn0Vg==/base.apk
      arm64: [status=speed-profile] [reason=bg-dexopt] [primary-abi]
        [location is /data/app/~~dzJiGMKvp22vi2SsvfjkrQ==/com.google.samples.apps.nowinandroid.demo-7FR1sdJ8ZTy7eCLwAnn0Vg==/oat/arm64/base.odex]

Wartość stanu wskazuje stan kompilacji profilu i jest jedną z tych wartości:

Stan kompilacji Znaczenie
speed‑profile Istnieje skompilowany profil, który jest używany.
verify Nie ma skompilowanego profilu.

Stan verify nie oznacza, że plik APK lub AAB nie zawiera profilu, ponieważ może być w kolejce do skompilowania przez następne zadanie optymalizacji DEX w tle.

Wartość reason wskazuje, co wywołuje kompilację profilu, i jest jedną z tych wartości:

Przyczyna Znaczenie
install‑dm Profil podstawowy został skompilowany ręcznie lub przez Google Play podczas instalacji aplikacji.
bg‑dexopt Profil został utworzony, gdy urządzenie było nieaktywne. Może to być profil podstawowy lub profil zebrany podczas korzystania z aplikacji.
cmdline Kompilacja została wywołana za pomocą narzędzia adb. Może to być profil podstawowy lub profil zebrany podczas korzystania z aplikacji.

Weryfikacja zgłoszenia profilu startupu do DEX i r8.json

Reguły profilu uruchamiania są używane podczas kompilacji przez R8 do optymalizacji układu klas w plikach DEX. Ta optymalizacja w czasie kompilacji różni się od sposobu używania profili podstawowych (baseline.prof), ponieważ są one pakowane w APK lub AAB, aby ART mógł przeprowadzać kompilację na urządzeniu. Reguły profilu uruchamiania są stosowane podczas samego procesu kompilacji, więc w pliku APK lub AAB nie ma oddzielnego pliku startup.prof, który można by sprawdzić. Efekt profili uruchamiania jest widoczny w układzie pliku DEX.

Sprawdzanie układu DEX za pomocą r8.json (zalecane w przypadku AGP 8.8 lub nowszego)

W przypadku projektów korzystających z wtyczki Androida do obsługi Gradle (AGP) w wersji 8.8 lub nowszej możesz sprawdzić, czy profil uruchamiania został zastosowany, sprawdzając wygenerowany plik r8.json. Ten plik jest spakowany w pakiecie AAB.

  1. Otwórz archiwum AAB i znajdź plik r8.json.
  2. Wyszukaj w pliku tablicę dexFiles, która zawiera listę wygenerowanych plików DEX.
  3. Poszukaj dexFiles obiektu zawierającego parę klucz-wartość "startup": true. Wyraźnie wskazuje to, że reguły profilu uruchamiania zostały zastosowane w celu zoptymalizowania układu tego konkretnego pliku DEX.

    "dexFiles": [
     {
       "checksum": "...",
       "startup": true // This flag confirms profile application to this DEX file
     },
     // ... other DEX files
    ]
    

Sprawdzanie rozmieszczenia plików DEX we wszystkich wersjach wtyczki Androida do obsługi Gradle

Jeśli używasz AGP w wersji niższej niż 8.8, sprawdzanie plików DEX jest głównym sposobem weryfikacji, czy profil uruchamiania został prawidłowo zastosowany. Możesz też użyć tej metody, jeśli korzystasz z wtyczki Androida do obsługi Gradle w wersji 8.8 lub nowszej i chcesz ręcznie sprawdzić układ DEX. Na przykład jeśli nie widzisz oczekiwanej poprawy skuteczności. Aby sprawdzić umowę DEX, wykonaj te czynności:

  1. Otwórz plik AAB lub APK w Android Studio, klikając Build > Analyze APK (Utwórz > Przeanalizuj APK).
  2. Przejdź do pierwszego pliku DEX. Na przykład: classes.dex.
  3. Sprawdź zawartość tego pliku DEX. Powinno być możliwe sprawdzenie, czy krytyczne klasy i metody zdefiniowane w pliku profilu uruchamiania (startup-prof.txt) znajdują się w tym głównym pliku DEX. Prawidłowe zastosowanie tej techniki oznacza, że kluczowe dla uruchomienia komponenty są ładowane w pierwszej kolejności.

problemy z wydajnością,

W tej sekcji znajdziesz sprawdzone metody prawidłowego definiowania i porównywania profili podstawowych, które pozwolą Ci w pełni wykorzystać ich potencjał.

Prawidłowe porównywanie danych dotyczących uruchamiania

Profile podstawowe będą skuteczniejsze, jeśli dane dotyczące uruchamiania aplikacji będą dobrze zdefiniowane. Dwa kluczowe rodzaje danych to czas do początkowego wyświetlenia (TTID)czas do pełnego wyświetlenia (TTFD).

TTID to moment, w którym aplikacja rysuje pierwszą klatkę. Ważne jest, aby ten czas był jak najkrótszy, ponieważ wyświetlanie czegokolwiek pokazuje użytkownikowi, że aplikacja działa. Możesz nawet wyświetlić wskaźnik postępu o nieokreślonym stanie, aby pokazać, że aplikacja odpowiada na działania użytkownika.

TTFD to moment, w którym można wejść w interakcję z aplikacją. Warto zadbać o to, aby był jak najkrótszy, dzięki czemu użytkownicy nie będą się frustrować. Jeśli prawidłowo sygnalizujesz TTFD, informujesz system, że kod uruchamiany w drodze do TTFD jest częścią uruchamiania aplikacji. Dzięki temu system z większym prawdopodobieństwem umieści ten kod w profilu.

Utrzymuj jak najniższe wartości TTID i TTFD, aby aplikacja działała płynnie.

System może wykrywać TTID, wyświetlać go w Logcat i raportować w ramach testów porównawczych uruchamiania. System nie jest jednak w stanie określić czasu TTFD, dlatego to aplikacja musi zgłaszać, kiedy osiągnie w pełni wyrenderowany stan interaktywny. Możesz to zrobić, wywołując funkcję reportFullyDrawn() lub ReportDrawn, jeśli używasz Jetpack Compose. Jeśli masz kilka zadań w tle, które muszą zostać wykonane, zanim aplikacja zostanie w pełni narysowana, możesz użyć FullyDrawnReporter, jak opisano w artykule Poprawianie dokładności pomiaru czasu uruchamiania.

Profile biblioteki i profile niestandardowe

Podczas porównywania wpływu profili trudno jest oddzielić korzyści wynikające z profili aplikacji od profili dostarczonych przez biblioteki, takie jak biblioteki Jetpack. Podczas kompilacji pliku APK wtyczka Androida do obsługi Gradle dodaje wszystkie profile w zależnościach bibliotek, a także Twój profil niestandardowy. Jest to przydatne do optymalizacji ogólnej wydajności i zalecane w przypadku wersji produkcyjnych. Utrudnia to jednak pomiar dodatkowego wzrostu wydajności wynikającego z używania profilu niestandardowego.

Szybkim sposobem na ręczne sprawdzenie dodatkowej optymalizacji zapewnianej przez profil niestandardowy jest jego usunięcie i przeprowadzenie testów porównawczych. Następnie wymień go i ponownie uruchom testy porównawcze. Porównanie tych dwóch wartości pokaże optymalizacje zapewniane przez same profile biblioteki oraz przez profile biblioteki w połączeniu z Twoim profilem niestandardowym.

Automatyczny sposób porównywania profili polega na utworzeniu nowego wariantu kompilacji, który zawiera tylko profile biblioteki, a nie profil niestandardowy. Porównaj wartości referencyjne tego wariantu z wariantem wersji, który zawiera zarówno profile biblioteki, jak i profile niestandardowe. Poniższy przykład pokazuje, jak skonfigurować wariant, który zawiera tylko profile bibliotek. Dodaj do modułu konsumenta profilu nowy wariant o nazwie releaseWithoutCustomProfile, który zwykle jest modułem aplikacji:

Kotlin

android {
  ...
  buildTypes {
    ...
    // Release build with only library profiles.
    create("releaseWithoutCustomProfile") {
      initWith(release)
    }
    ...
  }
  ...
}
...
dependencies {
  ...
  // Remove the baselineProfile dependency.
  // baselineProfile(project(":baselineprofile"))
}

baselineProfile {
  variants {
    create("release") {
      from(project(":baselineprofile"))
    }
  }
}

Groovy

android {
  ...
  buildTypes {
    ...
    // Release build with only library profiles.
    releaseWithoutCustomProfile {
      initWith(release)
    }
    ...
  }
  ...
}
...
dependencies {
  ...
  // Remove the baselineProfile dependency.
  // baselineProfile ':baselineprofile"'
}

baselineProfile {
  variants {
    release {
      from(project(":baselineprofile"))
    }
  }
}

W przykładzie kodu powyżej usunięto zależność baselineProfile ze wszystkich wariantów i zastosowano ją tylko do wariantu release. Może się wydawać sprzeczne z intuicją, że profile biblioteki są nadal dodawane, gdy usunięto zależność od modułu producenta profilu. Ten moduł odpowiada jednak tylko za generowanie niestandardowego profilu. Wtyczka Androida do obsługi Gradle nadal działa w przypadku wszystkich wariantów i jest odpowiedzialna za uwzględnianie profili bibliotek.

Musisz też dodać nowy wariant do modułu generatora profili. W tym przykładzie moduł producenta ma nazwę :baselineprofile.

Kotlin

android {
  ...
    buildTypes {
      ...
      // Release build with only library profiles.
      create("releaseWithoutCustomProfile") {}
      ...
    }
  ...
}

Groovy

android {
  ...
    buildTypes {
      ...
      // Release build with only library profiles.
      releaseWithoutCustomProfile {}
      ...
    }
  ...
}

Gdy uruchamiasz test porównawczy w Android Studio, wybierz wariant releaseWithoutCustomProfile, aby zmierzyć wydajność tylko za pomocą profili biblioteki, lub wariant release, aby zmierzyć wydajność za pomocą profili biblioteki i profili niestandardowych.

Unikaj uruchamiania aplikacji zależnego od operacji wejścia/wyjścia

Jeśli aplikacja wykonuje wiele wywołań wejścia/wyjścia lub wywołań sieciowych podczas uruchamiania, może to negatywnie wpłynąć zarówno na czas uruchamiania aplikacji, jak i na dokładność testów porównawczych uruchamiania. Te wymagające wywołania mogą trwać nieokreślony czas, który może się zmieniać z czasem, a nawet między iteracjami tego samego testu porównawczego. Wywołania wejścia/wyjścia są zwykle lepsze niż wywołania sieciowe, ponieważ na te ostatnie mogą wpływać czynniki zewnętrzne i wewnętrzne. Unikaj połączeń sieciowych podczas uruchamiania. Jeśli użycie jednego z tych terminów jest nieuniknione, użyj terminu „wejście/wyjście”.

Zalecamy, aby architektura aplikacji obsługiwała uruchamianie aplikacji bez wywołań sieciowych ani wywołań wejścia/wyjścia, nawet jeśli ma to służyć tylko do testowania uruchamiania. Pozwala to zapewnić jak najmniejszą zmienność między różnymi iteracjami wartości porównawczych.

Jeśli Twoja aplikacja korzysta z Hilt, możesz podczas testów porównawczych w Microbenchmark i Hilt udostępniać fałszywe implementacje związane z wejściem/wyjściem.

Obejmuj wszystkie ważne ścieżki użytkowników

Ważne jest, aby w procesie generowania profilu podstawowego uwzględnić wszystkie ważne ścieżki użytkowników. Ścieżki użytkowników, które nie są objęte tymi profilami, nie zostaną przez nie ulepszone. Najskuteczniejsze profile podstawowe obejmują wszystkie typowe ścieżki użytkowników podczas uruchamiania aplikacji, a także ścieżki użytkowników w aplikacji, które są wrażliwe na wydajność, np. przewijanie list.

Testy A/B zmian profilu w czasie kompilacji

Profile uruchomieniowe i podstawowe są optymalizacją czasu kompilacji, więc bezpośrednie testowanie A/B różnych plików APK w Sklepie Google Play nie jest zwykle obsługiwane w przypadku wersji produkcyjnych. Aby ocenić wpływ w środowisku podobnym do produkcyjnego, rozważ te podejścia:

  • Wersja poza cyklem: prześlij wersję poza cyklem do niewielkiego odsetka użytkowników, która zawiera tylko zmianę profilu. Pozwala to zbierać rzeczywiste dane o różnicach w skuteczności.

  • Lokalne testy porównawcze: lokalnie porównuj wydajność aplikacji z zastosowanym profilem i bez niego. Pamiętaj jednak, że lokalne testy porównawcze pokazują najlepszy scenariusz dla profili, ponieważ nie uwzględniają efektów profili w chmurze z ART, które są obecne na urządzeniach produkcyjnych.