Aby dowiedzieć się, jak korzystać z biblioteki mikroporównawczych przez dodawanie zmian do kodu aplikacji, zapoznaj się z sekcją Krótkie wprowadzenie. Informacje o tym, jak przeprowadzić pełną konfigurację z bardziej skomplikowanymi zmianami w bazie kodu, znajdziesz w sekcji Pełna konfiguracja projektu.
Krótkie wprowadzenie
W 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 wydajności, wykonaj te czynności, aby wyłączyć debugowanie w aplikacji, więc zapisz to w lokalnej kopii roboczej bez wprowadzania zmian w systemie kontroli źródła.
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.3") }
Odlotowy
dependencies { implementation 'androidx.benchmark:benchmark-junit4:1.2.3' }
Użyj zależności
implementation
zamiastandroidTestImplementation
. Jeśli używaszandroidTestImplementation
, testy porównawcze się nie udają, ponieważ plik manifest biblioteki nie został scalony z plikiem manifestu aplikacji.Zaktualizuj typ kompilacji
debug
tak, aby nie można było go debugować:Kotlin
android { ... buildTypes { debug { isDebuggable = false } } }
Odlotowy
android { ... buildTypes { debug { debuggable false } } }
Zmień
testInstrumentationRunner
naAndroidBenchmarkRunner
:Kotlin
android { ... defaultConfig { testInstrumentationRunner = "androidx.benchmark.junit4.AndroidBenchmarkRunner" } }
Odlotowy
android { ... defaultConfig { testInstrumentationRunner "androidx.benchmark.junit4.AndroidBenchmarkRunner" } }
Dodaj instancję
BenchmarkRule
w pliku testowym w kataloguandroidTest
, aby dodać test porównawczy. Więcej informacji o tworzeniu testów porównawczych znajdziesz w artykule Tworzenie klasy mikroporównawczej.Ten fragment kodu pokazuje, jak dodać test porównawczy do testu z instrumentacją:
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ć analizę porównawczą, przejdź do sekcji Tworzenie zajęć w ramach mikroporównania.
Pełna konfiguracja projektu
Aby skonfigurować regularne testy porównawcze zamiast jednorazowych testów porównawczych, utwórz osobny moduł dla testów porównawczych. Dzięki temu będziesz mieć pewność, że ich konfiguracja, np. ustawienie debuggable
na false
, będzie oddzielona od zwykłych testów.
Dzięki mikrotestom mikroporównawczym kod jest uruchamiany bezpośrednio, dlatego umieść go w osobnym module Gradle i ustaw zależność od tego modułu, jak pokazano na ilustracji 1.
Aby dodać nowy moduł Gradle, możesz użyć kreatora modułów w Android Studio. Kreator utworzy moduł skonfigurowany wstępnie do testów porównawczych, z dodanym katalogiem porównawczym, a debuggable
ustawionym na false
.
Kliknij prawym przyciskiem myszy projekt lub moduł w panelu Projekt w Android Studio i kliknij Nowy > Moduł.
W panelu Szablony kliknij Analiza porównawcza.
Jako typ modułu analizy porównawczej wybierz Mikroporównanie.
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 analizy porównawczej:
Kotlin
dependencies { // The module name might be different. androidTestImplementation(project(":benchmarkable")) }
Odlotowy
dependencies { // The module name might be different. androidTestImplementation project(':benchmarkable') }
Tworzenie zajęć mikroporównawczych
Testy porównawcze to standardowe testy z instrumentacją. Aby utworzyć analizę porównawczą, użyj klasy BenchmarkRule
dostępnej w bibliotece. Aby porównać aktywności, użyj ActivityScenario
lub ActivityScenarioRule
. Aby porównać kod interfejsu, użyj @UiThreadTest
.
Ten kod pokazuje przykładową analizę porównawczą:
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łącz czas na potrzeby konfiguracji
Możesz wyłączyć czas w przypadku fragmentów kodu, których nie chcesz mierzyć blokiem runWithTimingDisabled{}
. Sekcje te zwykle zawierają jakiś kod, który należy uruchomić przy każdym powtórzeniu testu.
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 wewnątrz bloku measureRepeated
i wewnątrz runWithTimingDisabled
. Blok measureRepeated
jest uruchamiany wiele razy i może mieć wpływ na ogólny czas potrzebny do przeprowadzenia analizy porównawczej. Jeśli chcesz zweryfikować niektóre wyniki testu porównawczego, możesz podać ostatni wynik, zamiast robić to przy każdym powtórzeniu testu.
Przeprowadź test porównawczy
W Android Studio przeprowadź test porównawczy tak samo jak w przypadku każdego innego elementu @Test
, używając działania rynku obok klasy lub metody testowej, jak pokazano na rysunku 3.
Możesz też z poziomu wiersza poleceń uruchomić connectedCheck
, aby uruchomić wszystkie testy z określonego modułu Gradle:
./gradlew benchmark:connectedCheck
Albo pojedynczy test:
./gradlew benchmark:connectedCheck -P android.testInstrumentationRunnerArguments.class=com.example.benchmark.SampleBenchmark#benchmarkSomeWork
Wyniki testu porównawczego
Po udanym przeprowadzeniu mikrotestów dane 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ą również automatycznie kopiowane 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/
Domyślnie raport JSON jest zapisywany na dysku na urządzeniu w zewnętrznym udostępnionym folderze multimediów pakietu APK, 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 wydajności z dokładnością do wersji:
- Wartość „Debuggable” (Możliwość debugowania) jest ustawiona na
false
. - Używasz urządzenia fizycznego – emulatory nie są obsługiwane.
- Zegary są blokowane, jeśli urządzenie ma dostęp do roota.
- Poziom naładowania baterii urządzenia wynosi co najmniej 25%.
Jeśli którykolwiek z poprzednich testów się nie powiedzie, test porównawczy zgłosi błąd, co pozwoli uniknąć niedokładności pomiarów.
Aby pominąć określone typy błędów jako ostrzeżenia i uniemożliwić im zatrzymanie testu porównawczego, przekaż typ błędu w postaci listy oddzielonej przecinkami do argumentu instrumentacji androidx.benchmark.suppressErrors
.
Możesz go ustawić w skrypcie Gradle w ten sposób:
Kotlin
android { defaultConfig { … testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,LOW-BATTERY" } }
Odlotowy
android { defaultConfig { … testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,LOW-BATTERY" } }
Możesz też pomijać błędy z poziomu wiersza poleceń:
$ ./gradlew :benchmark:connectedCheck -P andoidtestInstrumentationRunnerArguments.androidx.benchmark.supperssErrors=DEBUGGABLE,LOW-BATTERY
Ograniczenie błędów umożliwia uruchomienie testu w nieprawidłowo skonfigurowanym stanie, a dane wyjściowe testu są celowo zmieniane przez dodanie nazw testowych z błędem. Na przykład przeprowadzanie testu porównawczego z możliwością debugowania z pominięciem kodu w poprzednim fragmencie powoduje dodanie nazw testowych przed znakiem DEBUGGABLE_
.
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy JavaScript jest wyłączony
- Tworzenie makroporównania
- Tworzenie mikroporównań bez użycia Gradle
- Tworzenie profili podstawowych {:#using-profile-rules}