Aby dowiedzieć się, jak używać biblioteki Microbenchmark, dodając zmiany do kodu aplikacji, zapoznaj się z sekcją Szybki start. Aby dowiedzieć się, jak przeprowadzić pełną konfigurację z bardziej skomplikowanymi zmianami w bazie kodu, zapoznaj się z sekcją Pełna konfiguracja projektu.
Krótkie wprowadzenie
Z tej sekcji dowiesz się, jak wypróbować testy porównawcze i przeprowadzić jednorazowe pomiary bez konieczności przenoszenia kodu do modułów. Aby uzyskać dokładne wyniki, musisz wyłączyć debugowanie w aplikacji. Zrób to w lokalnej kopii roboczej, nie zapisując zmian w systemie kontroli źródła.
Aby przeprowadzić jednorazową analizę porównawczą:
Dodaj bibliotekę do pliku
build.gradlelubbuild.gradle.ktsmodułu:Kotlin
dependencies { implementation("androidx.benchmark:benchmark-junit4:1.2.4") }
Dynamiczny
dependencies { implementation 'androidx.benchmark:benchmark-junit4:1.2.4' }
Użyj zależności
implementationzamiastandroidTestImplementation. Jeśli używaszandroidTestImplementation, testy porównawcze nie zostaną uruchomione, ponieważ manifest biblioteki nie jest scalony z manifestem aplikacji.Zaktualizuj typ kompilacji
debug, aby nie można było jej debugować:Kotlin
android { ... buildTypes { debug { isDebuggable = false } } }
Dynamiczny
android { ... buildTypes { debug { debuggable false } } }
Zmień
testInstrumentationRunnernaAndroidBenchmarkRunner:Kotlin
android { ... defaultConfig { testInstrumentationRunner = "androidx.benchmark.junit4.AndroidBenchmarkRunner" } }
Dynamiczny
android { ... defaultConfig { testInstrumentationRunner "androidx.benchmark.junit4.AndroidBenchmarkRunner" } }
Aby dodać test porównawczy, dodaj instancję
BenchmarkRulew pliku testowym w kataloguandroidTest. Więcej informacji o pisaniu testów porównawczych znajdziesz w artykule Tworzenie klasy Microbenchmark.Poniższy fragment kodu pokazuje, jak dodać test porównawczy do testu instrumentowanego:
Kotlin
@RunWith(AndroidJUnit4::class) class SampleBenchmark { @get:Rule val benchmarkRule = BenchmarkRule() @Test fun benchmarkSomeWork() { benchmarkRule.measureRepeated { doSomeWork() } } }
Java
@RunWith(AndroidJUnit4.class) class SampleBenchmark { @Rule public BenchmarkRule benchmarkRule = new BenchmarkRule(); @Test public void benchmarkSomeWork() { BenchmarkRuleKt.measureRepeated( (Function1<BenchmarkRule.Scope, Unit>) scope -> doSomeWork() ); } } }
Aby dowiedzieć się, jak napisać test porównawczy, przejdź do sekcji Tworzenie klasy Microbenchmark.
Pełna konfiguracja projektu
Aby skonfigurować regularne testy porównawcze, a nie jednorazowe, wyodrębnij je do osobnego modułu. Dzięki temu ich konfiguracja, np. ustawienie debuggable na false, jest oddzielona od zwykłych testów.
Ponieważ Microbenchmark uruchamia kod bezpośrednio, umieść kod, który chcesz przetestować, w osobnym module Gradle i ustaw zależność od tego modułu, jak pokazano na rysunku 1.
:app, :microbenchmark i :benchmarkable, która umożliwia mikrotestom porównawczym testowanie kodu w module :benchmarkable.Aby dodać nowy moduł Gradle, możesz użyć kreatora modułów w Android Studio. Kreator tworzy moduł wstępnie skonfigurowany do testów porównawczych, z dodanym katalogiem testów porównawczych i ustawieniem debuggable na false.
W panelu Projekt w Android Studio kliknij prawym przyciskiem myszy projekt lub moduł i wybierz Nowy > Moduł.
W panelu Szablony wybierz Analiza porównawcza.
Jako typ modułu testu porównawczego wybierz Microbenchmark.
Jako nazwę modułu wpisz „microbenchmark”.
Kliknij Zakończ.
Po utworzeniu modułu zmień jego plik build.gradle lub build.gradle.kts i dodaj androidTestImplementation do modułu zawierającego kod do testu porównawczego:
Kotlin
dependencies { // The module name might be different. androidTestImplementation(project(":benchmarkable")) }
Dynamiczny
dependencies { // The module name might be different. androidTestImplementation project(':benchmarkable') }
Tworzenie klasy Microbenchmark
Testy porównawcze to standardowe testy z instrumentacją. Aby utworzyć test porównawczy, użyj klasy BenchmarkRule udostępnianej przez bibliotekę. Aby przeprowadzić test porównawczy działań, użyj ActivityScenario lub ActivityScenarioRule. Aby przeprowadzić test porównawczy kodu interfejsu, użyj @UiThreadTest.
Poniższy kod pokazuje przykładowy test porównawczy:
Kotlin
@RunWith(AndroidJUnit4::class) class SampleBenchmark { @get:Rule val benchmarkRule = BenchmarkRule() @Test fun benchmarkSomeWork() { benchmarkRule.measureRepeated { doSomeWork() } } }
Java
@RunWith(AndroidJUnit4.class) class SampleBenchmark { @Rule public BenchmarkRule benchmarkRule = new BenchmarkRule(); @Test public void benchmarkSomeWork() { final BenchmarkState state = benchmarkRule.getState(); while (state.keepRunning()) { doSomeWork(); } } }
Wyłączanie czasu konfiguracji
Możesz wyłączyć pomiar czasu w przypadku fragmentów kodu, których nie chcesz mierzyć, za pomocą bloku runWithTimingDisabled{}. Te sekcje zwykle reprezentują kod, który należy uruchomić w każdej iteracji testu porównawczego.
Kotlin
// using random with the same seed, so that it generates the same data every run private val random = Random(0) // create the array once and just copy it in benchmarks private val unsorted = IntArray(10_000) { random.nextInt() } @Test fun benchmark_quickSort() { // ... benchmarkRule.measureRepeated { // copy the array with timing disabled to measure only the algorithm itself listToSort = runWithTimingDisabled { unsorted.copyOf() } // sort the array in place and measure how long it takes SortingAlgorithms.quickSort(listToSort) } // assert only once not to add overhead to the benchmarks assertTrue(listToSort.isSorted) }
Java
private final int[] unsorted = new int[10000]; public SampleBenchmark() { // Use random with the same seed, so that it generates the same data every // run. Random random = new Random(0); // Create the array once and copy it in benchmarks. Arrays.setAll(unsorted, (index) -> random.nextInt()); } @Test public void benchmark_quickSort() { final BenchmarkState state = benchmarkRule.getState(); int[] listToSort = new int[0]; while (state.keepRunning()) { // Copy the array with timing disabled to measure only the algorithm // itself. state.pauseTiming(); listToSort = Arrays.copyOf(unsorted, 10000); state.resumeTiming(); // Sort the array in place and measure how long it takes. SortingAlgorithms.quickSort(listToSort); } // Assert only once, not to add overhead to the benchmarks. assertTrue(SortingAlgorithmsKt.isSorted(listToSort)); }
Postaraj się zminimalizować ilość pracy wykonywanej w bloku measureRepeated i w runWithTimingDisabled. Blok measureRepeated jest uruchamiany wielokrotnie i może mieć wpływ na łączny czas potrzebny na przeprowadzenie testu porównawczego. Jeśli chcesz sprawdzić niektóre wyniki testu porównawczego, możesz potwierdzić ostatni wynik, zamiast robić to w każdej iteracji testu.
Uruchamianie testu porównawczego
W Android Studio uruchom test porównawczy tak samo jak każdy @Test, używając działania w rynience obok klasy lub metody testowej, jak pokazano na rysunku 3.
Możesz też uruchomić w wierszu poleceń polecenie connectedCheck, aby uruchomić wszystkie testy z określonego modułu Gradle:
./gradlew benchmark:connectedCheckMożesz też uruchomić pojedynczy test:
./gradlew benchmark:connectedCheck -P android.testInstrumentationRunnerArguments.class=com.example.benchmark.SampleBenchmark#benchmarkSomeWorkWyniki testu porównawczego
Po pomyślnym uruchomieniu Microbenchmark dane są wyświetlane bezpośrednio w Android Studio, a pełny raport z testu porównawczego z dodatkowymi danymi i informacjami o urządzeniu jest dostępny w formacie JSON.
Raporty JSON i wszelkie ślady profilowania są też automatycznie kopiowane z urządzenia na hosta. Są one zapisywane na maszynie hosta w tej lokalizacji:
project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/
Domyślnie raport JSON jest zapisywany na dysku na urządzeniu w zewnętrznym udostępnionym folderze multimediów testowego pakietu APK, który zwykle znajduje się w /storage/emulated/0/Android/media/**app_id**/**app_id**-benchmarkData.json.
Błędy konfiguracji
Biblioteka wykrywa te warunki, aby upewnić się, że projekt i środowisko są skonfigurowane pod kątem wydajności odpowiedniej dla wersji:
- Atrybut debuggable jest ustawiony na
false. - używasz urządzenia fizycznego – emulatory nie są obsługiwane;
- Zegary są zablokowane, jeśli urządzenie ma dostęp do roota.
- Wystarczający poziom baterii na urządzeniu (co najmniej 25%).
Jeśli któryś z tych testów zakończy się niepowodzeniem, test porównawczy zgłosi błąd, aby zapobiec niedokładnym pomiarom.
Aby ukryć określone typy błędów jako ostrzeżenia i zapobiec zatrzymaniu testu porównawczego, przekaż typ błędu na liście rozdzielonej przecinkami do argumentu instrumentacji androidx.benchmark.suppressErrors.
Możesz to ustawić w skrypcie Gradle, jak w tym przykładzie:
Kotlin
android { defaultConfig { … testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,LOW-BATTERY" } }
Dynamiczny
android { defaultConfig { … testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,LOW-BATTERY" } }
Możesz też ukryć błędy z poziomu wiersza poleceń:
$ ./gradlew :benchmark:connectedCheck -P andoidtestInstrumentationRunnerArguments.androidx.benchmark.supperssErrors=DEBUGGABLE,LOW-BATTERY
Pomijanie błędów umożliwia uruchomienie testu porównawczego w nieprawidłowo skonfigurowanym stanie, a dane wyjściowe testu porównawczego są celowo zmieniane przez dodanie błędów na początku nazw testów. Na przykład uruchomienie testu porównawczego z możliwością debugowania z pominięciem w poprzednim fragmencie kodu powoduje dodanie do nazw testów prefiksu DEBUGGABLE_.
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy język JavaScript jest wyłączony.
- Pisanie testu Macrobenchmark
- Tworzenie testów Microbenchmark bez Gradle
- Tworzenie profili podstawowych {:#creating-profile-rules}