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 LazyColumn lub uruchamianie animacji. Jeśli chcesz przetestować mniejsze obszary kodu, zapoznaj się z sekcją Mikrobenchmark. 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 trybie ciągłej integracji (CI), zgodnie z opisem w sekcji Benchmark w ciągłej integracji.
Za pomocą biblioteki Macrobenchmark możesz generować profile podstawowe. Najpierw skonfiguruj bibliotekę Macrobenchmark, a potem możesz utworzyć profil podstawowy.
Macrobenchmark to zalecane narzędzie do testowania interfejsów utworzonych za pomocą Jetpack Compose. Aby dowiedzieć się, jak pisać testy UI Automator, które wchodzą w interakcje z węzłami Compose, przeczytaj artykuł Współdziałanie.
Konfigurowanie projektu
Zalecamy używanie Macrobenchmark w najnowszej wersji Androida Studio.
Konfigurowanie modułu Macrobenchmark
Testy makro wymagają modułu com.android.test, który jest oddzielony od kodu aplikacji i odpowiada za przeprowadzanie testów pomiarowych 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:
W Android Studio kliknij prawym przyciskiem myszy projekt lub moduł w panelu Projekt i wybierz Nowy > Moduł.
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.
Kliknij Zakończ.
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 przechwytywania profilu i resetowania oraz czyszczenia pamięci podręcznej shaderów.
Skonfiguruj aplikację testową tak, aby była jak najbardziej zbliżona do wersji do publikacji lub produkcyjnej. Skonfiguruj go jako niedający się debugować i najlepiej z włączoną minifikacją, co poprawia wydajność. Zwykle robi się to, tworząc kopię wersji
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łowy wariant aplikacji (jak pokazano na rysunku 2), wykonaj te czynności:
- Przeprowadź synchronizację Gradle.
- Otwórz panel Warianty kompilacji.
- Wybierz wariant testu porównawczego zarówno aplikacji, jak i modułu Macrobenchmark.
(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 kompilacji benchmark modułów :macrobenchmark i :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 i :macrobenchmark oraz release w przypadku wszystkich innych modułów w aplikacji, jak pokazano na rysunku 3:
Więcej informacji znajdziesz w artykule Rozwiązywanie błędów kompilacji związanych z dopasowywaniem wariantów.
(Opcjonalnie) Konfigurowanie wersji produktów
Jeśli w aplikacji masz skonfigurowanych kilka wariantów usługi, skonfiguruj moduł :macrobenchmark, aby wiedział, który wariant usługi Twojej aplikacji ma tworzyć i do którego ma odnosić wyniki.
Przykłady na tej stronie korzystają z 2 wersji produktu w module :app: demo i production, jak pokazano we fragmencie kodu poniżej:
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 wystąpić błąd kompilacji podobny do tego, który jest spowodowany przez wiele 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 opisujemy sposoby konfigurowania testów porównawczych z użyciem wielu wersji produktu.
Używanie parametru missingDimensionStrategy
Określenie missingDimensionStrategy w defaultConfig modułu :macrobenchmark informuje system kompilacji, że ma użyć wymiaru wersji. 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:
Więcej informacji znajdziesz w artykule Rozwiązywanie błędów kompilacji związanych z dopasowywaniem wariantów.
Tworzenie klasy Macrobenchmark
Testy porównawcze są dostępne w ramach interfejsu API reguły MacrobenchmarkRule JUnit4 w bibliotece Macrobenchmark. Zawiera metodę measureRepeated, 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, przez którą ma być przeprowadzony 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) } } }
Wszystkie opcje dostosowywania wartości porównawczych znajdziesz w sekcji Dostosowywanie wartości porównawczych.
Testowanie interakcji w interfejsie Compose
W poprzednim przykładzie mierzyliśmy uruchamianie aplikacji, ale często warto mierzyć wydajność interfejsu, np. spadki liczby klatek (zacinanie) podczas przewijania.
Aby przeprowadzić test porównawczy aplikacji Jetpack Compose, np. zmierzyć FrameTimingMetric podczas przewijania LazyColumn, możesz użyć UI Automatora do bezpośredniego wchodzenia w interakcję z węzłami Compose, jak pokazano w tym fragmencie kodu.
@LargeTest
@RunWith(AndroidJUnit4::class)
class ComposeScrollBenchmark {
@get:Rule
val benchmarkRule = MacrobenchmarkRule()
@Test
fun scrollLazyColumn() = benchmarkRule.measureRepeated(
packageName = "com.example.compose.app",
metrics = listOf(FrameTimingMetric()),
iterations = 5,
startupMode = StartupMode.WARM,
setupBlock = { pressHome() }
) {
startActivityAndWait()
// Find the Compose node using the testTag defined in your app
val lazyColumn = device.findObject(By.res("my_lazy_column"))
// Simulate a scroll gesture to measure FrameTimingMetric
lazyColumn.setGestureMargin(device.displayWidth / 5)
lazyColumn.fling(Direction.DOWN)
}
}
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@Test, korzystając z działania w kolumnie obok klasy lub metody testowej, jak pokazano na rysunku 5.
Możesz też uruchomić wszystkie testy porównawcze w module Gradle z wiersza poleceń, wykonując polecenie connectedCheck:
./gradlew :macrobenchmark:connectedCheckAby uruchomić pojedynczy test, wykonaj te czynności:
./gradlew :macrobenchmark:connectedCheck -P android.testInstrumentationRunnerArguments.class=com.example.macrobenchmark.startup.SampleStartupBenchmark#startupWięcej informacji o uruchamianiu i monitorowaniu testów porównawczych 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 Android Studio i zapisywane w pliku JSON do wykorzystania w ciągłej integracji. Każda zmierzona iteracja rejestruje oddzielny ślad systemu. Aby otworzyć wyniki śledzenia, kliknij linki w panelu Wyniki testu, jak pokazano na ilustracji 6:
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:
Po wczytaniu pliku śledzenia Studio wyświetli wyniki w narzędziu profilowania procesora:
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 Androida Studio lub z wiersza poleceń Gradle, pliki śledzenia zostaną automatycznie skopiowane z urządzenia na hosta. Są one zapisywane na komputerze hosta 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.
Testy porównawcze Macrobenchmark zwracają też błędy podczas próby pomiaru na emulatorze lub urządzeniu z niskim poziomem baterii, co może negatywnie wpływać na dostępność rdzeni i szybkość zegara.
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 porównawczy.
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 Rejestrowanie danych testu porównawczego na poziomie makro.
Ulepszanie danych śledzenia za pomocą zdarzeń niestandardowych
Warto zaimplementować w aplikacji niestandardowe zdarzenia śledzenia, które są widoczne w raporcie śledzenia i mogą pomóc w wykryciu problemów specyficznych dla 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 (poziom interfejsu API 24) i nowszym.
Jeśli używasz Androida 6 (poziom interfejsu API 23) lub starszego, domyślnym zachowaniem systemu jest pełna kompilacja pakietu 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 z wyprzedzeniem (AOT) 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 zapobiec zakłóceniom 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.
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy język JavaScript jest wyłączony.
- Zbieranie danych testu porównawczego
- Tworzenie profili podstawowych {:#creating-profile-rules}
- Automatyzacja pomiarów za pomocą biblioteki Macrobenchmark {:#measuring-optimization}