เขียนเกณฑ์เปรียบเทียบขนาดเล็ก

ดูวิธีใช้ไลบรารี Microbenchmark โดยเพิ่มการเปลี่ยนแปลงลงในโค้ดของแอปพลิเคชัน ได้ในส่วนคู่มือเริ่มใช้งานฉบับย่อ ดูวิธีตั้งค่าให้เสร็จสมบูรณ์ด้วยการเปลี่ยนแปลงที่ซับซ้อนมากขึ้นในฐานของโค้ดได้ในส่วน การตั้งค่าโปรเจ็กต์แบบเต็ม

การเริ่มต้นอย่างรวดเร็ว

ส่วนนี้จะแสดงวิธีลองใช้การเปรียบเทียบประสิทธิภาพและเรียกใช้การวัดแบบครั้งเดียวโดยไม่ต้องย้ายโค้ดไปยังโมดูล ขั้นตอนเหล่านี้เกี่ยวข้องกับการปิดใช้การแก้ไขข้อบกพร่องในแอปเพื่อให้ได้ผลลัพธ์ประสิทธิภาพที่ถูกต้อง ดังนั้นให้เก็บการเปลี่ยนแปลงนี้ไว้ในสำเนาที่ใช้งานในเครื่องโดยไม่ต้องคอมมิตการเปลี่ยนแปลงไปยังระบบควบคุมเวอร์ชัน

หากต้องการทำการเปรียบเทียบประสิทธิภาพแบบครั้งเดียว ให้ทำดังนี้

  1. เพิ่มไลบรารีลงในไฟล์ build.gradle หรือ build.gradle.kts ของโมดูล

    Kotlin

    dependencies {
        implementation("androidx.benchmark:benchmark-junit4:1.2.4")
    }

    ดึงดูด

    dependencies {
        implementation 'androidx.benchmark:benchmark-junit4:1.2.4'
    }

    ใช้ทรัพยากร Dependency implementation แทนทรัพยากร Dependency androidTestImplementation หากใช้ androidTestImplementation การเปรียบเทียบประสิทธิภาพจะทำงานไม่สำเร็จเนื่องจากระบบจะไม่ผสานไฟล์ Manifest ของไลบรารีเข้ากับไฟล์ Manifest ของแอป

  2. อัปเดตประเภทบิลด์ debug เพื่อให้แก้ไขข้อบกพร่องไม่ได้

    Kotlin

    android {
        ...
        buildTypes {
            debug {
                isDebuggable = false
            }
        }
    }

    ดึงดูด

    android {
        ...
        buildTypes {
            debug {
                debuggable false
            }
        }
    }
  3. เปลี่ยน testInstrumentationRunner เป็น AndroidBenchmarkRunner

    Kotlin

    android {
        ...
        defaultConfig {
            testInstrumentationRunner = "androidx.benchmark.junit4.AndroidBenchmarkRunner"
        }
    }

    ดึงดูด

    android {
        ...
        defaultConfig {
            testInstrumentationRunner "androidx.benchmark.junit4.AndroidBenchmarkRunner"
        }
    }
  4. เพิ่มอินสแตนซ์ของ 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

โครงสร้างแอป
รูปที่ 1 โครงสร้างแอปที่มีโมดูล Gradle :app, :microbenchmark, และ :benchmarkable ซึ่งช่วยให้ Microbenchmarks เปรียบเทียบประสิทธิภาพของโค้ดในโมดูล :benchmarkable ได้

หากต้องการเพิ่มโมดูล Gradle ใหม่ คุณสามารถใช้วิซาร์ดโมดูลใน Android Studio ได้ วิซาร์ดจะสร้างโมดูลที่กำหนดค่าไว้ล่วงหน้าสำหรับการเปรียบเทียบประสิทธิภาพ โดยจะเพิ่มไดเรกทอรีการเปรียบเทียบประสิทธิภาพและตั้งค่า debuggable เป็น false

  1. คลิกขวาที่โปรเจ็กต์หรือโมดูลในแผงโปรเจ็กต์ ใน Android Studio แล้วคลิกใหม่ > โมดูล

  2. เลือกการเปรียบเทียบประสิทธิภาพ ในแผงเทมเพลต

  3. เลือกการเปรียบเทียบประสิทธิภาพแบบ Microbenchmark เป็นประเภทโมดูลการเปรียบเทียบประสิทธิภาพ

  4. พิมพ์ "microbenchmark" เป็นชื่อโมดูล

  5. คลิกเสร็จสิ้น

กำหนดค่าโมดูลคลังใหม่
รูปที่ 2 เพิ่มโมดูล Gradle ใหม่ใน Android Studio Bumblebee.

หลังจากสร้างโมดูลแล้ว ให้เปลี่ยน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 โดยใช้การดำเนินการใน Gutter ข้างคลาสหรือเมธอดทดสอบ ดังที่แสดงในรูปที่ 3

เรียกใช้ Microbenchmark
รูปที่ 3 เรียกใช้การทดสอบ Microbenchmark โดยใช้การดำเนินการใน Gutter ข้างคลาสทดสอบ

หรือเรียกใช้ connectedCheck จากบรรทัดคำสั่งเพื่อเรียกใช้การทดสอบทั้งหมด จากโมดูล Gradle ที่ระบุ

./gradlew benchmark:connectedCheck

หรือการทดสอบเดียว

./gradlew benchmark:connectedCheck -P android.testInstrumentationRunnerArguments.class=com.example.benchmark.SampleBenchmark#benchmarkSomeWork

ผลการเปรียบเทียบประสิทธิภาพ

หลังจากเรียกใช้ Microbenchmark สำเร็จ ระบบจะแสดงเมตริกใน Android Studio โดยตรง และรายงานการเปรียบเทียบประสิทธิภาพแบบเต็มพร้อมเมตริกเพิ่มเติมและข้อมูลอุปกรณ์จะอยู่ในรูปแบบ JSON

ผลลัพธ์การทดสอบประสิทธิภาพระดับไมโคร
รูปที่ 4 ผลการเปรียบเทียบประสิทธิภาพแบบ Microbenchmark

ระบบจะคัดลอกรายงาน 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

เกิดข้อผิดพลาดในการกำหนดค่า

ไลบรารีจะตรวจพบเงื่อนไขต่อไปนี้เพื่อให้แน่ใจว่าโปรเจ็กต์และสภาพแวดล้อมได้รับการตั้งค่าให้มีประสิทธิภาพที่ถูกต้องสำหรับการเผยแพร่

  • ตั้งค่า Debuggable เป็น 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_