透過新增變更至應用程式程式碼,即可快速開始使用 Microbenchmark 程式庫。如要正確設定專案,請按照需要更複雜變更程式碼集的完整設定一節操作。
快速入門
本節提供試用基準化和一次性測量的快速導覽,您無須將程式碼移入模組。為了獲得準確的效能結果,以下步驟包含停用應用程式的偵錯功能,因此您應在本機作業副本中保留此功能,而不需要變更來源控制系統。
如要快速執行一次性基準化,請執行下列步驟:
將程式庫新增至模組的
build.gradle
檔案:project_root/module_dir/build.gradle
Groovy
dependencies { androidTestImplementation 'androidx.benchmark:benchmark-junit4:1.1.0-beta03' }
Kotlin
dependencies { androidTestImplementation("androidx.benchmark:benchmark-junit4:1.1.0-beta03") }
如要停用測試資訊清單中的偵錯功能,請更新
<application>
元素,暫時強制停用偵錯功能:project_root/module_dir/src/androidTest/AndroidManifest.xml
<!-- Important: disable debuggable for accurate performance results --> <application android:debuggable="false" tools:ignore="HardcodedDebugMode" tools:replace="android:debuggable"/>
如要新增基準,請在
androidTest
目錄中的測試檔案中新增BenchmarkRule
例項。如要進一步瞭解編寫基準的資訊,請參閱建立 Microbenchmark 類別。下列程式碼片段說明如何在 JUnit 測試中新增基準:
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(); } } }
如要瞭解如何編寫基準,請略過至建立 Microbenchmark 類別 section.
完整專案設定
如要設定一般基準化,而非一次性基準化,請將基準隔離到各自的模組中。這可確保其設定 (例如將 debuggable
設為 false
) 與一般測試各自獨立。
由於 Microbenchmark 直接執行您的程式碼,因此您必須將要做為基準的程式碼放入獨立的 Gradle 模組,並設定對模組的依附元件,如下圖所示。
如要新增 Gradle 模組,您可以使用 Android Studio 中的模組精靈。此精靈會建立為基準預先設定的模組,並新增基準目錄,同時將 debuggable
設為 false
。
Bumblebee (或更新版本)
- 在 Android Studio 的「Project」(專案)面板中的專案或模組,按一下滑鼠右鍵您,然後按一下「Add」(新增) >「Module」(模組)。
- 在「Templates」(範本) 窗格中選取「Benchmark」(基準)。
- 選取 Microbenchmark 做為基準模組類型。
- 輸入模組名稱的 Microbenchmark。
- 按一下「Finish」(完成)。
Arctic Fox
- 在 Android Studio 的「Project」(專案)面板中的專案或模組,按一下滑鼠右鍵您,然後按一下「Add」(新增) >「Module」(模組)。
- 在「Templates」(範本) 窗格中選取「Benchmark」(基準)。
- 輸入模組名稱的 Microbenchmark。
- 按一下「Finish」(完成)。
建立模組後,請變更其 build.gradle
檔案,並將 testImplementation
新增至含有基準程式碼的模組:
Groovy
dependencies { // Note, that the module name may be different androidTestImplementation project(':benchmarkable') }
Kotlin
dependencies { // Note, that the module name may be different androidTestImplementation(project(":benchmarkable")) }
建立 Microbenchmark 類別
基準屬於標準檢測設備測試。如要建立基準,請使用程式庫提供的 BenchmarkRule
類別。如要基準化活動,請使用 ActivityTestRule
或 ActivityScenarioRule
。如要基準化 UI 程式碼,請使用 @UiThreadTest
。
下列程式碼代表範本基準:
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(); } } }
停用設定時間
您可以停用不想透過 runWithTimingDisabled{}
區塊測量的程式碼區段時間。這些區段通常代表每次基準疊代時需要執行的部分程式碼。
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() { // using random with the same seed, so that it generates the same data every run Random random = new Random(0); // create the array once and just 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
的基準測試,如下圖所示。
或者,從指令列執行 connectedCheck
,以從指定的 Gradle 模組執行所有測試:
./gradlew benchmark:connectedCheck
或單一測試:
./gradlew benchmark:connectedCheck -P android.testInstrumentationRunnerArguments.class=com.example.benchmark.SampleBenchmark#benchmarkSomeWork
基準測試結果
Microbenchmark 順利執行後,就能直接在 Android Studio 中顯示指標,以及提供其他指標和裝置資訊的完整基準報表,而裝置資訊則以 JSON 格式提供。androidx.benchmark
Gradle 外掛程式根據預設為啟用 JSON 輸出。
根據預設,JSON 報表會寫入測試 APK 的外部共用媒體資料夾中的裝置端,通常位於 /storage/emulated/0/Android/media/app_id/app_id-benchmarkData.json。
此外,JSON 報表也會自動從裝置複製到主機。這些寫入主體機器的內容如下:
project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/app_id-benchmarkData.json
設定錯誤
程式庫會偵測下列條件,確保您的專案和環境都設定妥當,以釋出準確效能:
- 可進行偵錯設定為
false
。 - 正在使用的實體裝置 (不支援模擬器)。
- 已啟用 Root 權限的裝置時鐘會遭到鎖定。
- 裝置具備足夠電池電量 (至少 25%)。
如果以上任何檢查失敗,基準都會回報錯誤,避免進行不正確的測量。
如要略過警告的特定錯誤類型,並避免警告中止基準測試,請透過以半形逗號分隔的清單將錯誤類型傳遞至檢測引數 androidx.benchmark.suppressErrors
。
您可以透過您的 Gradle 指令碼設定,如下所示:
Groovy
android { defaultConfig { … testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,LOW-BATTERY" } }
Kotlin
android { defaultConfig { … testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,LOW-BATTERY" } }
封鎖錯誤時,基準就能以錯誤設定的狀態執行,且基準的輸出內容則會透過含錯誤的預先測試名稱刻意重新命名。例如,在上述程式碼片段中,執行封鎖的可進行偵錯基準將在 DEBUGGABLE_
前面加上測試名稱。