Aby dowiedzieć się, jak korzystać z biblioteki Microbenchmark, wprowadzając zmiany w kodzie aplikacji, zapoznaj się z sekcją Krótkie wprowadzenie. Aby dowiedzieć się, jak przeprowadzić pełną konfigurację z bardziej skomplikowanymi zmianami w kodzie, przeczytaj sekcję Pełna konfiguracja projektu.
Krótkie wprowadzenie
Z tej sekcji dowiesz się, jak przeprowadzić test porównawczy i jednorazowe pomiary bez konieczności przenoszenia kodu do modułów. Aby uzyskać dokładne wyniki dotyczące wydajności, te kroki obejmują wyłączenie debugowania w aplikacji, więc zachowaj te dane w lokalnej kopii roboczej bez wprowadzania zmian w systemie sterowania źródłem.
Aby przeprowadzić jednorazową analizę porównawczą:
Dodaj bibliotekę do pliku
build.gradle
lubbuild.gradle.kts
modułu:Kotlin
dependencies { implementation("androidx.benchmark:benchmark-junit4:1.2.4") }
Groovy
dependencies { implementation 'androidx.benchmark:benchmark-junit4:1.2.4' }
Zamiast zależności
androidTestImplementation
użyj zależnościimplementation
. Jeśli używaszandroidTestImplementation
, testy porównawcze nie są wykonywane, ponieważ manifest biblioteki nie jest scalany z plikiem manifestu aplikacji.Zaktualizuj typ kompilacji
debug
, aby nie można było go debugować:Kotlin
android { ... buildTypes { debug { isDebuggable = false } } }
Odlotowe
android { ... buildTypes { debug { debuggable false } } }
Zmień
testInstrumentationRunner
naAndroidBenchmarkRunner
:Kotlin
android { ... defaultConfig { testInstrumentationRunner = "androidx.benchmark.junit4.AndroidBenchmarkRunner" } }
Groovy
android { ... defaultConfig { testInstrumentationRunner "androidx.benchmark.junit4.AndroidBenchmarkRunner" } }
Aby dodać wartość testu porównawczego, dodaj instancję funkcji
BenchmarkRule
w pliku testowym w kataloguandroidTest
. Więcej informacji o tworzeniu testów porównawczych znajdziesz w artykule Tworzenie klasy testów mikroporównawczych.Ten fragment kodu pokazuje, jak dodać punkt odniesienia do testu z użyciem pomiarów:
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 testów mikroporównawczych.
Pełna konfiguracja projektu
Aby skonfigurować regularne testy porównawcze zamiast jednorazowych, wyodrębnij testy porównawcze w osobnym module. Dzięki temu ich konfiguracja (np. ustawienie debuggable
na false
) będzie odrębna od zwykłych testów.
Ponieważ Microbenchmark uruchamia kod bezpośrednio, umieść kod, który chcesz przetestować, w oddzielnym module Gradle i ustaw zależność od tego modułu, jak pokazano na rysunku 1.
Aby dodać nowy moduł Gradle, możesz użyć kreatora modułów w Android Studio. Kreator tworzy moduł wstępnie skonfigurowany do porównywania, z dodanym katalogiem porównywania 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 kliknij Porównanie.
Jako typ modułu porównawczego wybierz Microbenchmark (Test porównawczy mikrobenchmarków).
Jako nazwę modułu wpisz „microbenchmark”.
Kliknij Zakończ.
Po utworzeniu modułu zmień jego plik build.gradle
lub build.gradle.kts
i dodaj do modułu zawierającego kod do testów porównawczych element androidTestImplementation
:
Kotlin
dependencies { // The module name might be different. androidTestImplementation(project(":benchmarkable")) }
Groovy
dependencies { // The module name might be different. androidTestImplementation project(':benchmarkable') }
Tworzenie klasy mikrotestów
Wskaźniki to standardowe testy z wykorzystaniem instrumentacji. Aby utworzyć punkt odniesienia, użyj klasy BenchmarkRule
udostępnionej przez bibliotekę. Aby porównać aktywność, użyj kolumny ActivityScenario
lub ActivityScenarioRule
. Aby porównać kod interfejsu, użyj narzędzia @UiThreadTest
.
Poniższy kod pokazuje przykładowe testy porównawcze:
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 ustawień czasu
Za pomocą bloku runWithTimingDisabled{}
możesz wyłączyć pomiar czasu w sekcjach kodu, których nie chcesz mierzyć. Sekcje te zazwyczaj zawierają kod, który należy uruchamiać przy 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)); }
Spróbuj zminimalizować ilość pracy wykonywanej w bloku measureRepeated
i w bloku runWithTimingDisabled
. Blok measureRepeated
jest uruchamiany wiele razy i może wpłynąć na ogólny czas potrzebny na przeprowadzenie testu porównawczego. Jeśli chcesz zweryfikować niektóre wyniki testu porównawczego, możesz potwierdzić ostatni wynik zamiast weryfikować go po każdej iteracji testu.
Przeprowadzanie testu porównawczego
W Android Studio uruchom test porównawczy tak jak dowolną funkcję @Test
, korzystając z działania w sekcji ścieżki obok testowanej klasy lub metody, jak pokazano na rysunku 3.
Możesz też uruchomić connectedCheck
z wiersza poleceń, aby uruchomić wszystkie testy z określonego modułu Gradle:
./gradlew benchmark:connectedCheck
Możesz też wybrać pojedynczy test:
./gradlew benchmark:connectedCheck -P android.testInstrumentationRunnerArguments.class=com.example.benchmark.SampleBenchmark#benchmarkSomeWork
Wyniki testów porównawczych
Po udanym przeprowadzeniu testu porównawczego mikrodane są wyświetlane bezpośrednio w Android Studio, a pełny raport porównawczy z dodatkowymi danymi i informacjami o urządzeniach jest dostępny w formacie JSON.
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/
Domyślnie raport w formacie JSON jest zapisywany na dysku urządzenia w zewnętrznym folderze udostępnionych multimediów pliku APK testowego, który zwykle znajduje się w folderze /storage/emulated/0/Android/media/**app_id**/**app_id**-benchmarkData.json
.
Błędy konfiguracji
Biblioteka wykrywa te warunki, aby zapewnić, że projekt i środowisko są skonfigurowane pod kątem dokładności działania w wersji:
- Debuggable ma wartość
false
. - Używane jest urządzenie fizyczne – emulatory nie są obsługiwane.
- Zegary są zablokowane, jeśli urządzenie ma dostęp do roota.
- Urządzenie musi mieć co najmniej 25% poziom naładowania baterii.
Jeśli którykolwiek z poprzednich testów zakończy się niepowodzeniem, benchmark zgłosi błąd, aby uniknąć niedokładnych pomiarów.
Aby pominąć wyświetlanie określonych typów błędów jako ostrzeżeń i uniemożliwić im zatrzymanie testu porównawczego, prześlij typ błędu w postaci listy oddzielonych przecinkami do argumentu androidx.benchmark.suppressErrors
.
Możesz to ustawić w skrypcie Gradle, jak pokazano w tym przykładzie:
Kotlin
android { defaultConfig { … testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,LOW-BATTERY" } }
Odlotowe
android { defaultConfig { … testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,LOW-BATTERY" } }
Błędy możesz też pomijać z poziomu wiersza poleceń:
$ ./gradlew :benchmark:connectedCheck -P andoidtestInstrumentationRunnerArguments.androidx.benchmark.supperssErrors=DEBUGGABLE,LOW-BATTERY
Funkcja pomijania błędów umożliwia przeprowadzanie testu w nieprawidłowo skonfigurowanym stanie, a dane wyjściowe są celowo zmieniane przez nazwy testów z błędem na początku. Na przykład uruchomienie testu porównawczego z możliwością debugowania i wyłączeniem w poprzednim fragmencie kodu powoduje, że nazwy testów są poprzedzone symbolem DEBUGGABLE_
.
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy obsługa JavaScript jest wyłączona
- Tworzenie testu porównawczego makro
- Tworzenie mikrobenchmarków bez Gradle
- Tworzenie profili podstawowych {:#creating-profile-rules}