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 wykonać jednorazowe pomiary bez konieczności przenoszenia kodu do modułów. Aby uzyskać dokładne wyniki dotyczące wydajności, wykonaj te czynności, które obejmują wyłączenie debugowania w aplikacji. Dlatego zachowaj lokalną kopię roboczą bez zatwierdzania zmian w systemie kontroli wersji.
Aby przeprowadzić jednorazowe porównanie, wykonaj te czynności:
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.Zmień typ kompilacji
debug
, aby nie można było go debugować:Kotlin
android { ... buildTypes { debug { isDebuggable = false } } }
Groovy
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
, jest oddzielona 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ł, a potem 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 zajęć z mikrobenchmarkami
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 @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
Możesz wyłączyć pomiar czasu w sekcjach kodu, których nie chcesz mierzyć, za pomocą bloku runWithTimingDisabled{}
. Te sekcje zwykle reprezentują kod, który musisz uruchomić w przypadku 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 wykonywany wielokrotnie i może wpływać na łączny czas potrzebny do przeprowadzenia 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 rynny 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 testu porównawczego
Po pomyślnym uruchomieniu mikrotestu dane są wyświetlane bezpośrednio w Android Studio, a pełny raport testów porównawczych z dodatkowymi danymi i informacjami o urządzeniu jest dostępny w formacie JSON.
Raporty w formacie 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.
- Wystarczający poziom naładowania baterii urządzenia (co najmniej 25%).
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, przekaż typ błędu w postaci listy oddzielonych przecinkami do argumentu instrumentacji 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" } }
Groovy
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
Pomijanie błędów umożliwia uruchomienie testu w nieprawidłowo skonfigurowanym stanie, a wynik testu jest celowo przemianowany przez dodanie do nazwy testu błędu. Na przykład uruchomienie testu porównawczego z możliwością debugowania z wyłączeniem w poprzednim fragmencie kodu powoduje, że nazwy testów mają przedrostek 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}