ดูวิธีใช้คลัง Microbenchmark ด้วยการเพิ่มการเปลี่ยนแปลงลงในโค้ดแอปพลิเคชันได้ที่ส่วนเริ่มต้นใช้งานอย่างรวดเร็ว หากต้องการดูวิธีตั้งค่าให้เสร็จสมบูรณ์ด้วยการเปลี่ยนแปลงโค้ดเบสที่ซับซ้อนมากขึ้น โปรดดูส่วนการตั้งค่าโปรเจ็กต์แบบสมบูรณ์
การเริ่มต้นใช้งานอย่างรวดเร็ว
ส่วนนี้จะแสดงวิธีลองใช้การเปรียบเทียบและทำการวัดผลแบบครั้งเดียวโดยไม่ต้องย้ายโค้ดไปยังโมดูล ขั้นตอนเหล่านี้เกี่ยวข้องกับการปิดใช้การแก้ไขข้อบกพร่องในแอปเพื่อให้ได้ผลลัพธ์ประสิทธิภาพที่ถูกต้อง ดังนั้นโปรดเก็บสำเนาที่ทำงานนี้ไว้ในพื้นที่ทำงานโดยไม่บันทึกการเปลี่ยนแปลงในระบบควบคุมแหล่งที่มา
หากต้องการทำการเปรียบเทียบแบบครั้งเดียว ให้ทําดังนี้
เพิ่มไลบรารีลงในไฟล์
build.gradle
หรือbuild.gradle.kts
ของโมดูล โดยทำดังนี้Kotlin
dependencies { implementation("androidx.benchmark:benchmark-junit4:1.2.4") }
Groovy
dependencies { implementation 'androidx.benchmark:benchmark-junit4:1.2.4' }
ใช้
implementation
แทนandroidTestImplementation
หากคุณใช้androidTestImplementation
เบนช์มาร์กจะทํางานไม่ได้เนื่องจากระบบไม่ได้ผสานไฟล์ Manifest ของไลบรารีเข้ากับไฟล์ Manifest ของแอปอัปเดตประเภทบิลด์
debug
เพื่อไม่ให้แก้ไขข้อบกพร่องได้ โดยทำดังนี้Kotlin
android { ... buildTypes { debug { isDebuggable = false } } }
Groovy
android { ... buildTypes { debug { debuggable false } } }
เปลี่ยน
testInstrumentationRunner
เป็นAndroidBenchmarkRunner
Kotlin
android { ... defaultConfig { testInstrumentationRunner = "androidx.benchmark.junit4.AndroidBenchmarkRunner" } }
Groovy
android { ... defaultConfig { testInstrumentationRunner "androidx.benchmark.junit4.AndroidBenchmarkRunner" } }
เพิ่มอินสแตนซ์ของ
BenchmarkRule
ในไฟล์ทดสอบในไดเรกทอรีandroidTest
เพื่อเพิ่มการเปรียบเทียบ ดูข้อมูลเพิ่มเติมเกี่ยวกับการเขียนการเปรียบเทียบได้ที่สร้างคลาสการเปรียบเทียบประสิทธิภาพระดับไมโครข้อมูลโค้ดต่อไปนี้แสดงวิธีเพิ่มการเปรียบเทียบกับมาตรฐานในการทดสอบที่มีเครื่องมือวัด
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() ); } } }
หากต้องการดูวิธีเขียนการเปรียบเทียบ ให้ข้ามไปที่หัวข้อสร้างคลาสการเปรียบเทียบประสิทธิภาพระดับไมโคร
การตั้งค่าโปรเจ็กต์แบบสมบูรณ์
หากต้องการตั้งค่าการเปรียบเทียบปกติแทนการเปรียบเทียบแบบครั้งเดียว ให้แยกการเปรียบเทียบออกเป็นโมดูลของตัวเอง วิธีนี้ช่วยให้มั่นใจว่าการกําหนดค่า เช่น การตั้งค่า debuggable
เป็น false
จะแยกจากการทดสอบปกติ
เนื่องจาก Microbenchmark จะเรียกใช้โค้ดโดยตรง ให้วางโค้ดที่ต้องการทำการทดสอบประสิทธิภาพไว้ในโมดูล Gradle แยกต่างหากและตั้งค่าการพึ่งพาในโมดูลนั้นตามที่แสดงในรูปที่ 1
หากต้องการเพิ่มโมดูล Gradle ใหม่ ให้ใช้วิซาร์ดโมดูลใน Android Studio วิซาร์ดจะสร้างโมดูลที่กำหนดค่าไว้ล่วงหน้าสำหรับการเปรียบเทียบ โดยเพิ่มไดเรกทอรีการเปรียบเทียบและตั้งค่า debuggable
เป็น false
คลิกขวาที่โปรเจ็กต์หรือโมดูลในแผงโปรเจ็กต์ใน Android Studio แล้วคลิกใหม่ > โมดูล
เลือกการเปรียบเทียบในแผงเทมเพลต
เลือก Microbenchmark เป็นประเภทโมดูลการเปรียบเทียบ
พิมพ์ "microbenchmark" เป็นชื่อโมดูล
คลิกเสร็จสิ้น
หลังจากสร้างโมดูลแล้ว ให้เปลี่ยนไฟล์ build.gradle
หรือ build.gradle.kts
และเพิ่ม androidTestImplementation
ลงในโมดูลที่มีโค้ดเพื่อเปรียบเทียบ
Kotlin
dependencies { // The module name might be different. androidTestImplementation(project(":benchmarkable")) }
Groovy
dependencies { // The module name might be different. androidTestImplementation project(':benchmarkable') }
สร้างคลาสการทดสอบประสิทธิภาพระดับไมโคร
การเปรียบเทียบเป็นการทดสอบการวัดผลมาตรฐาน หากต้องการสร้างการเปรียบเทียบ ให้ใช้คลาส 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
หรือเรียกใช้ connectedCheck
จากบรรทัดคำสั่งเพื่อเรียกใช้การทดสอบทั้งหมดจากโมดูล Gradle ที่ระบุ
./gradlew benchmark:connectedCheck
หรือทดสอบครั้งเดียว
./gradlew benchmark:connectedCheck -P android.testInstrumentationRunnerArguments.class=com.example.benchmark.SampleBenchmark#benchmarkSomeWork
ผลลัพธ์การเปรียบเทียบ
หลังจากการเรียกใช้การทดสอบประสิทธิภาพแบบไมโครเสร็จสมบูรณ์แล้ว เมตริกจะแสดงใน 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
ข้อผิดพลาดในการกําหนดค่า
ไลบรารีจะตรวจหาเงื่อนไขต่อไปนี้เพื่อให้แน่ใจว่าโปรเจ็กต์และสภาพแวดล้อมได้รับการตั้งค่าเพื่อประสิทธิภาพที่ถูกต้องของรุ่น
- ตั้งค่า "แก้ไขได้" เป็น
false
- มีการใช้อุปกรณ์จริง ระบบไม่รองรับโปรแกรมจำลอง
- นาฬิกาจะล็อกอยู่หากอุปกรณ์มีการรูท
- แบตเตอรี่ในอุปกรณ์มีระดับเพียงพออย่างน้อย 25%
หากการตรวจสอบก่อนหน้านี้ไม่สําเร็จ เบนช์มาร์กจะรายงานข้อผิดพลาดเพื่อไม่ให้มีการวัดผลที่ไม่ถูกต้อง
หากต้องการซ่อนข้อผิดพลาดบางประเภทเป็นคําเตือนและป้องกันไม่ให้ข้อผิดพลาดเหล่านั้นหยุดการทดสอบประสิทธิภาพ ให้ส่งประเภทข้อผิดพลาดเป็นรายการที่คั่นด้วยคอมมาไปยังอาร์กิวเมนต์เครื่องมือวัดประสิทธิภาพ androidx.benchmark.suppressErrors
คุณตั้งค่านี้ได้จากสคริปต์ Gradle ดังตัวอย่างต่อไปนี้
Kotlin
android { defaultConfig { … testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,LOW-BATTERY" } }
Groovy
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}