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

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

คู่มือเริ่มต้นฉบับย่อ

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

ในการเปรียบเทียบแบบครั้งเดียว ให้ทำดังนี้

  1. เพิ่มไลบรารีลงในไฟล์ 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

  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 โครงสร้างแอปที่มี :app :microbenchmark และ :benchmarkable Gradle ซึ่งทำให้โค้ดเปรียบเทียบ Microbenchmarks สามารถ :benchmarkable โมดูล

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

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

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

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

  4. พิมพ์ "Microbenchmark" สำหรับชื่อโมดูล

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

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

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

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

./gradlew benchmark:connectedCheck

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

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

ผลการเปรียบเทียบ

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

วันที่ ผลการเปรียบเทียบไมโคร
รูปที่ 4 เปรียบเทียบผลลัพธ์ในระดับไมโคร

รายงาน 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_ ไว้ข้างหน้าชื่อการทดสอบ