Чтобы узнать, как использовать библиотеку Microbenchmark путем внесения изменений в код приложения, см. раздел «Краткий старт» . Чтобы узнать, как выполнить полную настройку с более сложными изменениями в вашей кодовой базе, см. раздел Полная настройка проекта .
Быстрый старт
В этом разделе показано, как опробовать бенчмаркинг и провести разовые измерения без необходимости перемещения кода в модули. Для получения точных результатов производительности эти шаги включают в себя отключение отладки в вашем приложении, поэтому сохраните ее в локальной рабочей копии, не внося изменений в систему управления версиями.
Чтобы выполнить одноразовый бенчмаркинг, выполните следующие действия:
Добавьте библиотеку в файл
build.gradle
илиbuild.gradle.kts
вашего модуля:Котлин
dependencies { implementation("androidx.benchmark:benchmark-junit4:1.2.4") }
классный
dependencies { implementation 'androidx.benchmark:benchmark-junit4:1.2.4' }
Используйте зависимость
implementation
вместо зависимостиandroidTestImplementation
. Если вы используетеandroidTestImplementation
, тесты не выполняются, поскольку манифест библиотеки не объединяется с манифестом приложения.Обновите тип
debug
сборки, чтобы его нельзя было отлаживать:Котлин
android { ... buildTypes { debug { isDebuggable = false } } }
классный
android { ... buildTypes { debug { debuggable false } } }
Измените
testInstrumentationRunner
наAndroidBenchmarkRunner
:Котлин
android { ... defaultConfig { testInstrumentationRunner = "androidx.benchmark.junit4.AndroidBenchmarkRunner" } }
классный
android { ... defaultConfig { testInstrumentationRunner "androidx.benchmark.junit4.AndroidBenchmarkRunner" } }
Добавьте экземпляр
BenchmarkRule
в тестовый файл в каталогеandroidTest
, чтобы добавить свой тест. Дополнительные сведения о написании тестов см. в разделе Создание класса Microbenchmark .В следующем фрагменте кода показано, как добавить тест к инструментированному тесту:
Котлин
@RunWith(AndroidJUnit4::class) class SampleBenchmark { @get:Rule val benchmarkRule = BenchmarkRule() @Test fun benchmarkSomeWork() { benchmarkRule.measureRepeated { doSomeWork() } } }
Ява
@RunWith(AndroidJUnit4.class) class SampleBenchmark { @Rule public BenchmarkRule benchmarkRule = new BenchmarkRule(); @Test public void benchmarkSomeWork() { BenchmarkRuleKt.measureRepeated( (Function1<BenchmarkRule.Scope, Unit>) scope -> doSomeWork() ); } } }
Чтобы узнать, как написать тест, перейдите к разделу «Создание класса Microbenchmark» .
Полная настройка проекта
Чтобы организовать регулярное тестирование, а не разовое тестирование, выделите тесты в отдельный модуль. Это помогает гарантировать, что их конфигурация, такая как установка debuggable
значения false
, отделена от обычных тестов.
Поскольку Microbenchmark запускает ваш код напрямую, поместите код, который вы хотите протестировать, в отдельный модуль Gradle и установите зависимость от этого модуля, как показано на рисунке 1.
Чтобы добавить новый модуль Gradle, вы можете использовать мастер модулей в Android Studio. Мастер создает модуль, предварительно настроенный для тестирования производительности, с добавленным каталогом тестирования и debuggable
установленным на false
.
Щелкните правой кнопкой мыши проект или модуль на панели «Проект» в Android Studio и выберите «Создать» > «Модуль» .
Выберите «Бенчмарк» на панели «Шаблоны» .
Выберите Microbenchmark в качестве типа модуля тестирования.
Введите «микробенчмарк» в качестве имени модуля.
Нажмите «Готово» .
После создания модуля измените его файл build.gradle
или build.gradle.kts
и добавьте androidTestImplementation
в модуль, содержащий код для тестирования:
Котлин
dependencies { // The module name might be different. androidTestImplementation(project(":benchmarkable")) }
классный
dependencies { // The module name might be different. androidTestImplementation project(':benchmarkable') }
Создайте класс Microbenchmark
Бенчмарки — это стандартные инструментальные тесты. Чтобы создать тест, используйте класс BenchmarkRule
предоставляемый библиотекой. Для сравнения действий используйте ActivityScenario
или ActivityScenarioRule
. Чтобы протестировать код пользовательского интерфейса, используйте @UiThreadTest
.
Следующий код показывает пример теста:
Котлин
@RunWith(AndroidJUnit4::class) class SampleBenchmark { @get:Rule val benchmarkRule = BenchmarkRule() @Test fun benchmarkSomeWork() { benchmarkRule.measureRepeated { doSomeWork() } } }
Ява
@RunWith(AndroidJUnit4.class) class SampleBenchmark { @Rule public BenchmarkRule benchmarkRule = new BenchmarkRule(); @Test public void benchmarkSomeWork() { final BenchmarkState state = benchmarkRule.getState(); while (state.keepRunning()) { doSomeWork(); } } }
Отключить время для настройки
Вы можете отключить синхронизацию для разделов кода, которые вы не хотите измерять, с помощью блока runWithTimingDisabled{}
. Эти разделы обычно представляют собой некоторый код, который необходимо запускать на каждой итерации теста.
Котлин
// 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) }
Ява
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)); }
Постарайтесь минимизировать объем работы, выполняемой внутри блока measureRepeated
и внутри runWithTimingDisabled
. Блок measureRepeated
запускается несколько раз, и это может повлиять на общее время, необходимое для выполнения теста. Если вам нужно проверить некоторые результаты теста, вы можете подтвердить последний результат вместо того, чтобы делать это на каждой итерации теста.
Запустите тест
В Android Studio запустите тест, как и любой @Test
используя действие поля рядом с вашим тестовым классом или методом, как показано на рисунке 3.
Альтернативно, из командной строки запустите connectedCheck
, чтобы запустить все тесты из указанного модуля Gradle:
./gradlew benchmark:connectedCheck
Или одиночный тест:
./gradlew benchmark:connectedCheck -P android.testInstrumentationRunnerArguments.class=com.example.benchmark.SampleBenchmark#benchmarkSomeWork
Результаты тестов
После успешного запуска Microbenchmark метрики отображаются непосредственно в Android Studio, а полный отчет о тестировании с дополнительными метриками и информацией об устройстве доступен в формате JSON.
Отчеты JSON и любые трассировки профилирования также автоматически копируются с устройства на хост. Они записываются на хост-компьютере в следующем месте:
project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/
По умолчанию отчет JSON записывается на диск устройства во внешнюю общую медиа-папку тестового APK, которая обычно находится в /storage/emulated/0/Android/media/**app_id**/**app_id**-benchmarkData.json
.
Ошибки конфигурации
Библиотека определяет следующие условия, чтобы гарантировать, что ваш проект и среда настроены для производительности с точностью до выпуска:
- Для параметра Debugable установлено значение
false
. - Используется физическое устройство — эмуляторы не поддерживаются.
- Часы блокируются, если устройство рутировано.
- Достаточный уровень заряда батареи на устройстве не менее 25%.
Если какая-либо из предыдущих проверок не удалась, эталонный тест сообщает об ошибке, чтобы предотвратить неточные измерения.
Чтобы подавить определенные типы ошибок в качестве предупреждений и предотвратить остановку теста производительности, передайте тип ошибки в списке, разделенном запятыми, в аргумент инструментария androidx.benchmark.suppressErrors
.
Вы можете установить это из своего сценария Gradle, как показано в следующем примере:
Котлин
android { defaultConfig { … testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,LOW-BATTERY" } }
классный
android { defaultConfig { … testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,LOW-BATTERY" } }
Вы также можете подавить ошибки из командной строки:
$ ./gradlew :benchmark:connectedCheck -P andoidtestInstrumentationRunnerArguments.androidx.benchmark.supperssErrors=DEBUGGABLE,LOW-BATTERY
Подавление ошибок позволяет тесту работать в неправильно настроенном состоянии, а выходные данные теста намеренно переименовываются путем добавления к имени теста ошибки. Например, при запуске отлаживаемого теста с подавлением в предыдущем фрагменте к именам тестов добавляется DEBUGGABLE_
.
Рекомендуется для вас
- Примечание. Текст ссылки отображается, когда JavaScript отключен.
- Напишите макробенчмарк
- Создание микротестов без Gradle
- Создание базовых профилей {:#creating-profile-rules}