Utwórz makroporównawczy

Biblioteki Macrobenchmark używaj do testowania większych przypadków użycia w aplikacji, w tym uruchamiania aplikacji i złożonych manipulacji interfejsem, takich jak przewijanie RecyclerView lub uruchamianie animacji. Jeśli chcesz testować mniejsze obszary kodu, zapoznaj się z informacjami o bibliotece Microbenchmark. Na tej stronie dowiesz się, jak skonfigurować bibliotekę Macrobenchmark.

Biblioteka wyświetla wyniki testów porównawczych w konsoli Android Studio i w pliku JSON zawierającym więcej szczegółów. Udostępnia też pliki śledzenia, które możesz wczytać i analizować w Android Studio.

Używaj biblioteki Macrobenchmark w środowisku ciągłej integracji (CI), zgodnie z opisem w sekcji Benchmark w trybie ciągłej integracji.

Za pomocą biblioteki Macrobenchmark możesz generować profile podstawowe. Najpierw skonfiguruj bibliotekę Macrobenchmark, a potem możesz utworzyć profil podstawowy.

Konfigurowanie projektu

Zalecamy używanie Macrobenchmark z najnowszą wersją Androida Studio, aby korzystać z funkcji środowiska IDE zintegrowanych z Macrobenchmark.

Konfigurowanie modułu Macrobenchmark

Testy makro wymagają modułu com.android.test oddzielonego od kodu aplikacji, który odpowiada za przeprowadzanie testów mierzących wydajność aplikacji.

W Android Studio dostępny jest szablon, który upraszcza konfigurację modułu Macrobenchmark. Szablon modułu testów porównawczych automatycznie tworzy w projekcie moduł do pomiaru aplikacji utworzonej przez moduł aplikacji, w tym przykładowy test porównawczy uruchamiania.

Aby utworzyć nowy moduł za pomocą szablonu modułu:

  1. W Android Studio kliknij prawym przyciskiem myszy projekt lub moduł w panelu Projekt i wybierz Nowy > Moduł.

  2. W panelu Szablony kliknij Analiza porównawcza. Możesz dostosować aplikację docelową, czyli aplikację, która ma być testowana, a także nazwę pakietu i modułu nowego modułu Macrobenchmark.

  3. Kliknij Zakończ.

Szablon modułu testu porównawczego

Rysunek 1. Szablon modułu porównawczego.

Konfigurowanie aplikacji

Aby przeprowadzić test porównawczy aplikacji, czyli celu testu Macrobenchmark, musi ona być profileable, co umożliwia odczytywanie szczegółowych informacji o śledzeniu bez wpływu na wydajność. Kreator modułów automatycznie dodaje tag <profileable> do pliku AndroidManifest.xml aplikacji.

Upewnij się, że aplikacja docelowa zawiera ProfilerInstaller w wersji 1.3 lub nowszej, która jest potrzebna bibliotece Macrobenchmark do włączania rejestrowania profili, resetowania i czyszczenia pamięci podręcznej shaderów.

Skonfiguruj aplikację testową tak, aby była jak najbardziej zbliżona do wersji do publikacji lub produkcyjnej. Ustaw go jako niedający się debugować i najlepiej z włączoną minimalizacją, co poprawia wydajność. Zwykle polega to na utworzeniu kopii wersji, która działa tak samo, ale jest podpisywana lokalnie za pomocą kluczy debugowania. Możesz też użyć initWith, aby zlecić to Gradle:

Kotlin

buildTypes {
    getByName("release") {
        isMinifyEnabled = true
        isShrinkResources = true
        proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"))
    }

    create("benchmark") {
        initWith(getByName("release"))
        signingConfig = signingConfigs.getByName("debug")
    }
}

Dynamiczny

buildTypes {
    release {
        isMinifyEnabled = true
        isShrinkResources = true
        proguardFiles(
            getDefaultProguardFile("proguard-android-optimize.txt"),
            "keep-rules.pro"
        )
        // In real app, this would use its own release keystore
        signingConfig = signingConfigs.getByName("debug")
        baselineProfile.automaticGenerationDuringBuild = true
    }
}

Aby mieć pewność, że test porównawczy tworzy i testuje prawidłową odmianę aplikacji (jak pokazano na rysunku 2), wykonaj te czynności:

  1. Przeprowadź synchronizację Gradle.
  2. Otwórz panel Warianty kompilacji.
  3. Wybierz wariant testu porównawczego zarówno aplikacji, jak i modułu Macrobenchmark.

Wybierz wariant testu porównawczego

Rysunek 2. Wybierz wariant porównawczy.

(Opcjonalnie) Konfigurowanie aplikacji wielomodułowej

Jeśli Twoja aplikacja ma więcej niż 1 moduł Gradle, upewnij się, że skrypty kompilacji wiedzą, który wariant kompilacji należy skompilować. Dodaj właściwośćmatchingFallbacks do rodzaju kompilacjibenchmark modułów :macrobenchmark:app. Pozostałe moduły Gradle mogą mieć taką samą konfigurację jak wcześniej.

Kotlin

create("benchmark") {
    initWith(getByName("release"))
    signingConfig = signingConfigs.getByName("debug")

    matchingFallbacks += listOf("release")
 }

Dynamiczny

benchmark {
    initWith buildTypes.release
    signingConfig signingConfigs.debug

    matchingFallbacks = ['release']
 }

Bez tego nowo dodany rodzaj kompilacji benchmark spowoduje niepowodzenie kompilacji i wyświetlenie tego komunikatu o błędzie:

> Could not resolve project :shared.
     Required by:
         project :app
      > No matching variant of project :shared was found.
      ...

Podczas wybierania wariantów kompilacji w projekcie wybierz benchmark w przypadku modułów :app:macrobenchmark oraz release w przypadku wszystkich innych modułów w aplikacji, jak pokazano na rysunku 3:

Wersje porównawcze w przypadku projektu wielomodułowego z wybranymi typami kompilacji wersji i kompilacji porównawczej

Rysunek 3. Warianty testu porównawczego dla projektu wielomodułowego z wybranymi typami kompilacji wydania i testu porównawczego.

Więcej informacji znajdziesz w artykule Korzystanie z zarządzania zależnościami z uwzględnieniem wariantów.

(Opcjonalnie) Konfigurowanie wersji produktów

Jeśli w aplikacji masz skonfigurowanych kilka wersji produktu, skonfiguruj moduł :macrobenchmark, aby wiedział, którą wersję aplikacji ma tworzyć i w stosunku do której ma przeprowadzać testy porównawcze.

Przykłady na tej stronie korzystają z 2 wersji produktu w module :app: demoproduction, jak pokazano w tym fragmencie kodu:

Kotlin

flavorDimensions += "environment"
productFlavors {
    create("demo") {
        dimension = "environment"
        // ...
    }
    create("production") {
        dimension = "environment"
        // ...
    }
}

Dynamiczny

flavorDimensions 'environment'
productFlavors {
    demo {
        dimension 'environment'
        // ...
    }

    production {
        dimension 'environment'
        // ...
    }
}

Bez tej konfiguracji może pojawić się błąd kompilacji podobny do tego, który występuje w przypadku wielu modułów Gradle:

Could not determine the dependencies of task ':macrobenchmark:connectedBenchmarkAndroidTest'.
> Could not determine the dependencies of null.
   > Could not resolve all task dependencies for configuration ':macrobenchmark:benchmarkTestedApks'.
      > Could not resolve project :app.
        Required by:
            project :macrobenchmark
         > The consumer was configured to find a runtime of a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'benchmark', attribute 'com.android.build.api.attributes.AgpVersionAttr' with value '7.3.0'. However we cannot choose between the following variants of project :app:
             -   demoBenchmarkRuntimeElements
             -   productionBenchmarkRuntimeElements
           All of them match the consumer attributes:
           ...

W 2 sekcjach poniżej znajdziesz sposoby konfigurowania testów porównawczych z użyciem wielu wersji produktu.

Używanie parametru missingDimensionStrategy

Określenie missingDimensionStrategydefaultConfig modułu :macrobenchmark informuje system kompilacji, że ma użyć wymiaru rodzajów. Określ, których wymiarów chcesz używać, jeśli nie znajdziesz ich w module. W poniższym przykładzie production smak jest używany jako domyślny wymiar:

Kotlin

defaultConfig {
    missingDimensionStrategy("environment", "production")
}

Dynamiczny

defaultConfig {
    missingDimensionStrategy "environment", "production"
}

Dzięki temu moduł :macrobenchmark może tworzyć i testować tylko określony wariant produktu, co jest przydatne, jeśli wiesz, że tylko jeden wariant produktu ma odpowiednią konfigurację do przeprowadzenia testu porównawczego.

Definiowanie wersji produktu w module :macrobenchmark

Jeśli chcesz tworzyć i porównywać inne wersje produktu, zdefiniuj je w module :macrobenchmark. Określ go podobnie jak w module :app, ale przypisz tylko productFlavors do dimension. Nie są wymagane żadne inne ustawienia:

Kotlin

flavorDimensions += "environment"
productFlavors {
    create("demo") {
        dimension = "environment"
    }
    create("production") {
        dimension = "environment"
    }
}

Dynamiczny

flavorDimensions 'environment'
productFlavors {
    demo {
        dimension 'environment'
    }

    production {
        dimension 'environment'
    }
}

Po zdefiniowaniu i zsynchronizowaniu projektu wybierz odpowiedni wariant kompilacji w panelu Warianty kompilacji, jak pokazano na rysunku 4:

Warianty porównawcze projektu z wersjami produktu, w których wyświetlane są wartości porównawcze produkcji i wersje

Rysunek 4. Warianty referencyjne projektu z wybranymi wersjami produktu „productionBenchmark” i „release”.

Więcej informacji znajdziesz w artykule Rozwiązywanie błędów kompilacji związanych z dopasowywaniem wariantów.

Tworzenie klasy makrobenchmarku

Testy porównawcze są dostępne w interfejsie API reguły MacrobenchmarkRule JUnit4 w bibliotece Macrobenchmark. Zawiera ona measureRepeated metodę, która umożliwia określanie różnych warunków uruchamiania i testowania aplikacji docelowej.

Musisz podać co najmniej packageName aplikacji docelowej, rodzaj metrics, który chcesz zmierzyć, oraz liczbę iterations, które musi uruchomić test porównawczy.

Kotlin

@LargeTest
@RunWith(AndroidJUnit4::class)
class SampleStartupBenchmark {
    @get:Rule
    val benchmarkRule = MacrobenchmarkRule()

    @Test
    fun startup() = benchmarkRule.measureRepeated(
        packageName = TARGET_PACKAGE,
        metrics = listOf(StartupTimingMetric()),
        iterations = DEFAULT_ITERATIONS,
    ) {
        // starts default launch activity
        uiAutomator { startApp(TARGET_PACKAGE) }
    }
}

Java

@LargeTest
@RunWith(AndroidJUnit4.class)
public class SampleStartupBenchmark {
    @Rule
    public MacrobenchmarkRule benchmarkRule = new MacrobenchmarkRule();

    @Test
    public void startup() {
        benchmarkRule.measureRepeated(
            /* packageName */ TARGET_PACKAGE,
            /* metrics */ Arrays.asList(new StartupTimingMetric()),
            /* iterations */ 5,
            /* measureBlock */ scope -> {
                // starts default launch activity
                scope.startActivityAndWait();
                return Unit.INSTANCE;
            }
        );
    }
}

Wszystkie opcje dostosowywania testu porównawczego znajdziesz w sekcji Dostosowywanie testów porównawczych.

Przeprowadź test porównawczy

Przeprowadź test w Android Studio, aby zmierzyć wydajność aplikacji na urządzeniu. Testy porównawcze możesz uruchamiać tak samo jak inne testy jednostkowe@Test, korzystając z działania na marginesie obok klasy lub metody testowej, jak pokazano na rysunku 5.

Uruchamianie testu Macrobenchmark z działaniem w kolumnie obok klasy testu

Rysunek 5. Uruchom Macrobenchmark z działaniem w kolumnie obok klasy testu.

Możesz też uruchomić wszystkie testy porównawcze w module Gradle z wiersza poleceń, wykonując polecenie connectedCheck:

./gradlew :macrobenchmark:connectedCheck

Aby uruchomić pojedynczy test, wykonaj te czynności:

./gradlew :macrobenchmark:connectedCheck -P android.testInstrumentationRunnerArguments.class=com.example.macrobenchmark.startup.SampleStartupBenchmark#startup

Informacje o tym, jak uruchamiać i monitorować testy porównawcze w trybie ciągłej integracji, znajdziesz w artykule Testy porównawcze w trybie ciągłej integracji.

Wyniki testu porównawczego

Po pomyślnym uruchomieniu testu porównawczego dane są wyświetlane bezpośrednio w Androidzie Studio i zapisywane w pliku JSON do wykorzystania w ciągłej integracji. Każda zmierzona iteracja rejestruje oddzielny ślad systemu. Wyniki śledzenia możesz otworzyć, klikając linki w panelu Wyniki testu, jak pokazano na ilustracji 6:

Wyniki testu Macrobenchmark dotyczącego uruchamiania aplikacji

Rysunek 6. Wyniki testu porównawczego uruchamiania.

Po wczytaniu śladu Android Studio wyświetli prośbę o wybranie procesu do analizy. Wybór jest wstępnie wypełniony procesem aplikacji docelowej, jak pokazano na rysunku 7:

Wybór procesu śledzenia Studio

Rysunek 7. Wybór procesu śledzenia w Studio.

Po wczytaniu pliku śledzenia Studio wyświetli wyniki w profilerze procesora:

Studio
Trace

Rysunek 8. Ślad Studio.

Raporty JSON i wszystkie ślady profilowania są też automatycznie kopiowane z urządzenia na hosta. Są one zapisywane na hoście w tym miejscu:

project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/

Ręczne uzyskiwanie dostępu do plików śledzenia

Jeśli chcesz użyć narzędzia Perfetto do analizy pliku śledzenia, musisz wykonać dodatkowe czynności. Perfetto umożliwia sprawdzanie wszystkich procesów zachodzących na urządzeniu podczas śledzenia, a profiler CPU w Android Studio ogranicza sprawdzanie do jednego procesu.

Jeśli wywołasz testy z Android Studio lub z wiersza poleceń Gradle, pliki śledzenia zostaną automatycznie skopiowane z urządzenia na hosta. Są one zapisywane na hoście w tej lokalizacji:

project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/TrivialStartupBenchmark_startup[mode=COLD]_iter002.perfetto-trace

Gdy plik śledzenia będzie już w systemie hosta, możesz go otworzyć w Android Studio, klikając w menu File > Open (Plik > Otwórz). Wyświetla widok narzędzia profilującego pokazany w poprzedniej sekcji.

Błędy konfiguracji

Jeśli aplikacja jest nieprawidłowo skonfigurowana (z możliwością debugowania lub bez możliwości profilowania), Macrobenchmark zwraca błąd zamiast podawać nieprawidłowe lub niekompletne pomiary. Możesz pominąć te błędy za pomocą argumentu androidx.benchmark.suppressErrors.

Macrobenchmark zwraca też błędy podczas próby pomiaru na emulatorze lub urządzeniu z niskim poziomem baterii, co może negatywnie wpłynąć na dostępność rdzeni i taktowanie.

Dostosowywanie punktów odniesienia

Funkcja measureRepeated akceptuje różne parametry, które wpływają na to, jakie dane zbiera biblioteka, jak uruchamiana i kompilowana jest aplikacja oraz ile iteracji wykonuje test.

Zbieranie danych

Dane to główny rodzaj informacji wyodrębnianych z testów porównawczych. Dostępne są te dane:

Więcej informacji o danych znajdziesz w artykule Zbieranie danych testu porównawczego na poziomie makro.

Ulepszanie danych śledzenia za pomocą zdarzeń niestandardowych

Warto dodać do aplikacji niestandardowe zdarzenia śledzenia, które będą widoczne w raporcie śledzenia i pomogą wskazać problemy specyficzne dla Twojej aplikacji. Więcej informacji o tworzeniu niestandardowych zdarzeń śledzenia znajdziesz w artykule Definiowanie zdarzeń niestandardowych.

CompilationMode

Testy porównawcze mogą określać CompilationMode, który definiuje, jaka część aplikacji musi być wstępnie skompilowana z kodu bajtowego DEX (format kodu bajtowego w pliku APK) do kodu maszynowego (podobnego do wstępnie skompilowanego kodu C++).

Domyślnie testy Macrobenchmark są uruchamiane z parametrem CompilationMode.DEFAULT, który instaluje profil podstawowy (jeśli jest dostępny) na Androidzie 7 (API na poziomie 24) i nowszym. Jeśli używasz Androida 6 (poziom interfejsu API 23) lub starszego, domyślnym zachowaniem systemu jest pełna kompilacja pliku APK w trybie kompilacji.

Profil podstawowy możesz zainstalować, jeśli aplikacja docelowa zawiera zarówno profil podstawowy, jak i bibliotekę ProfileInstaller.

Na Androidzie 7 i nowszym możesz dostosować parametr CompilationMode, aby wpływać na ilość wstępnej kompilacji na urządzeniu i symulować różne poziomy kompilacji AOT (ahead-of-time) lub buforowania JIT. Zobacz CompilationMode.Full, CompilationMode.Partial, CompilationMode.None i CompilationMode.Ignore.

Ta funkcja jest oparta na poleceniach kompilacji ART. Każdy test porównawczy czyści dane profilu przed rozpoczęciem, aby zapewnić brak zakłóceń między testami.

StartupMode

Aby rozpocząć aktywność, możesz przekazać wstępnie zdefiniowany tryb uruchamiania: COLD, WARM lub HOT. Ten parametr zmienia sposób uruchamiania aktywności i stan procesu na początku testu.

Więcej informacji o rodzajach uruchamiania znajdziesz w artykule Czas uruchamiania aplikacji.

Przykłady

Przykładowy projekt jest dostępny w Macrobenchmark Sample w repozytorium na GitHubie.

Prześlij opinię

Aby zgłosić problemy lub przesłać prośby o dodanie funkcji do biblioteki Jetpack Macrobenchmark, skorzystaj z publicznego narzędzia do śledzenia problemów.