หากต้องการเรียนรู้วิธีใช้ไลบรารี Microbenchmark โดยการเพิ่มการเปลี่ยนแปลง โค้ดของแอปพลิเคชัน โปรดดูที่ส่วนการเริ่มต้นอย่างรวดเร็ว ดูวิธีการ ตั้งค่าอย่างสมบูรณ์ด้วยการเปลี่ยนแปลงฐานของโค้ดที่ซับซ้อนมากขึ้นได้ที่ การตั้งค่าโปรเจ็กต์แบบเต็ม
คู่มือเริ่มต้นฉบับย่อ
ส่วนนี้จะแสดงวิธีลองใช้การเปรียบเทียบและเรียกใช้การวัดผลแบบครั้งเดียว โดยไม่จำเป็นต้องย้ายโค้ดไปยังโมดูล เพื่อผลลัพธ์ด้านประสิทธิภาพที่แม่นยำ ขั้นตอนเหล่านี้รวมไปถึงการปิดใช้การแก้ไขข้อบกพร่องในแอป ดังนั้นโปรดเก็บการตั้งค่านี้ไว้ใน สำเนาที่ใช้งานได้โดยไม่ต้องยืนยันการเปลี่ยนแปลงไปยังระบบควบคุมต้นทางของคุณ
ในการเปรียบเทียบแบบครั้งเดียว ให้ทำดังนี้
เพิ่มไลบรารีลงในไฟล์
build.gradle
หรือbuild.gradle.kts
ของโมดูล:Kotlin
dependencies { implementation("androidx.benchmark:benchmark-junit4:1.2.3") }
ดึงดูด
dependencies { implementation 'androidx.benchmark:benchmark-junit4:1.2.3' }
ใช้ทรัพยากร Dependency
implementation
แทนandroidTestImplementation
การพึ่งพา หากคุณใช้androidTestImplementation
การเปรียบเทียบจะไม่สำเร็จ ทำงานเนื่องจากไฟล์ Manifest ของไลบรารีไม่ได้ผสานเข้ากับแอป ไฟล์ Manifestอัปเดตประเภทบิลด์
debug
เพื่อให้แก้ไขข้อบกพร่องไม่ได้ โดยทำดังนี้Kotlin
android { ... buildTypes { debug { isDebuggable = false } } }
ดึงดูด
android { ... buildTypes { debug { debuggable false } } }
เปลี่ยน
testInstrumentationRunner
เป็นAndroidBenchmarkRunner
:Kotlin
android { ... defaultConfig { testInstrumentationRunner = "androidx.benchmark.junit4.AndroidBenchmarkRunner" } }
ดึงดูด
android { ... defaultConfig { testInstrumentationRunner "androidx.benchmark.junit4.AndroidBenchmarkRunner" } }
เพิ่มอินสแตนซ์ของ
BenchmarkRule
ในไฟล์ทดสอบในส่วน ไดเรกทอรีandroidTest
เพื่อเพิ่มการเปรียบเทียบ หากต้องการดูข้อมูลเพิ่มเติม เกี่ยวกับการเขียนการเปรียบเทียบ โปรดดูสร้างคลาส Microbenchmarkข้อมูลโค้ดต่อไปนี้แสดงวิธีเพิ่มการเปรียบเทียบในเครื่องมือวัด ทดสอบ:
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() ); } } }
หากต้องการดูวิธีเขียนการเปรียบเทียบ ให้ข้ามไปที่สร้างคลาส Microbenchmark
การตั้งค่าโปรเจ็กต์แบบเต็ม
หากต้องการตั้งค่าการเปรียบเทียบปกติแทนการเปรียบเทียบแบบครั้งเดียว ให้แยก
เปรียบเทียบเป็นโมดูลของตัวเอง ซึ่งช่วยรับประกันว่าการกำหนดค่า
เช่น การตั้งค่า debuggable
เป็น false
จะแยกต่างหากจากการทดสอบปกติ
เนื่องจาก Microbenchmark จะเรียกใช้โค้ดของคุณโดยตรง จึงควรวางโค้ดที่คุณต้องการ ลงในโมดูล Gradle ที่แยกต่างหาก แล้วตั้ง Dependency บนโมดูลนั้นเป็น ที่แสดงในรูปที่ 1
![โครงสร้างแอป](https://developer.android.com/static/topic/performance/images/benchmark_images/microbenchmark_modules.png?authuser=9&hl=th)
:app
:microbenchmark
และ :benchmarkable
Gradle
ซึ่งทำให้โค้ดเปรียบเทียบ Microbenchmarks สามารถ
:benchmarkable
โมดูลหากต้องการเพิ่มโมดูล Gradle ใหม่ ให้ใช้วิซาร์ดโมดูลใน Android Studio
วิซาร์ดจะสร้างโมดูลที่กำหนดค่าล่วงหน้าสำหรับการเปรียบเทียบ
เพิ่มไดเรกทอรีการเปรียบเทียบและตั้งค่า debuggable
เป็น false
แล้ว
คลิกขวาที่โปรเจ็กต์หรือโมดูลในแผงโปรเจ็กต์ใน Android Studio แล้วคลิกใหม่ > โมดูล
เลือกการเปรียบเทียบในแผงเทมเพลต
เลือกประเภทโมดูลการเปรียบเทียบเป็น Microbenchmark
พิมพ์ "Microbenchmark" สำหรับชื่อโมดูล
คลิกเสร็จสิ้น
![กำหนดค่าโมดูลคลังใหม่](https://developer.android.com/static/topic/performance/images/benchmark_images/microbenchmark_module_giraffe.png?authuser=9&hl=th)
หลังจากสร้างโมดูลแล้ว ให้เปลี่ยน build.gradle
หรือ build.gradle.kts
และเพิ่ม androidTestImplementation
ลงในโมดูลที่มีโค้ดสำหรับ
การเปรียบเทียบ:
Kotlin
dependencies { // The module name might be different. androidTestImplementation(project(":benchmarkable")) }
ดึงดูด
dependencies { // The module name might be different. androidTestImplementation project(':benchmarkable') }
สร้างคลาส Microbenchmark
การเปรียบเทียบเป็นการทดสอบการวัดคุมมาตรฐาน หากต้องการสร้างการเปรียบเทียบ ให้ใช้
ชั้นเรียน BenchmarkRule
ให้บริการโดยห้องสมุด หากต้องการเปรียบเทียบกิจกรรม ให้ใช้
ActivityScenario
หรือ 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() { // 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
![เรียกใช้ Microbenchmark](https://developer.android.com/static/topic/performance/images/benchmark_images/microbenchmark_run.png?authuser=9&hl=th)
หรือเรียกใช้ connectedCheck
จากบรรทัดคำสั่งเพื่อเรียกใช้ทั้งหมด
ของการทดสอบจากโมดูล Gradle ที่ระบุ
./gradlew benchmark:connectedCheck
หรือการทดสอบรายการเดียว
./gradlew benchmark:connectedCheck -P android.testInstrumentationRunnerArguments.class=com.example.benchmark.SampleBenchmark#benchmarkSomeWork
ผลการเปรียบเทียบ
หลังจากเรียกใช้ Microbenchmark สำเร็จ ระบบจะแสดงเมตริกใน Android โดยตรง Studio และรายงานการเปรียบเทียบฉบับเต็มพร้อมเมตริกและอุปกรณ์เพิ่มเติม มีให้ใช้งานในรูปแบบ JSON
![ผลการเปรียบเทียบไมโคร](https://developer.android.com/static/topic/performance/images/benchmark_images/microbenchmark_results.png?authuser=9&hl=th)
รายงาน 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
ข้อผิดพลาดในการกำหนดค่า
ไลบรารีจะตรวจหาเงื่อนไขต่อไปนี้เพื่อให้แน่ใจว่าโปรเจ็กต์และ มีการตั้งค่าสภาพแวดล้อมเพื่อประสิทธิภาพ ในการเผยแพร่ผลงานที่ถูกต้อง
- ตั้งค่าแก้ไขข้อบกพร่องเป็น
false
แล้ว - มีการใช้อุปกรณ์จริง จึงไม่รองรับโปรแกรมจำลอง
- นาฬิกาจะล็อกหากอุปกรณ์ผ่านการรูท
- ระดับแบตเตอรี่ที่เพียงพอในอุปกรณ์อย่างน้อย 25%
หากการตรวจสอบก่อนหน้าล้มเหลว การเปรียบเทียบจะรายงานข้อผิดพลาดเป็น ไม่สนับสนุนการวัดที่ไม่ถูกต้อง
เพื่อระงับข้อผิดพลาดบางประเภทเป็นคำเตือนและป้องกันไม่ให้เกิดการหยุด
เปรียบเทียบ ให้ส่งประเภทข้อผิดพลาดเป็นรายการที่คั่นด้วยจุลภาคไปยังเครื่องมือ
อาร์กิวเมนต์ androidx.benchmark.suppressErrors
คุณสามารถตั้งค่านี้ได้จากสคริปต์ Gradle ของคุณ ดังที่ปรากฏในตัวอย่างต่อไปนี้:
Kotlin
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}