Viết Microbenchmark

Bạn có thể nhanh chóng bắt đầu sử dụng thư viện Microbenchmark bằng cách thêm thay đổi vào mã ứng dụng của mình. Để thiết lập dự án đúng cách, hãy làm theo phần Thiết lập đầy đủ. Phần này đòi hỏi những thay đổi phức tạp hơn đối với mã cơ sở của bạn.

Bắt đầu nhanh

Phần này cung cấp hướng dẫn nhanh về cách dùng thử tính năng đo điểm chuẩn và chạy các phép đo một lần mà không yêu cầu bạn phải di chuyển mã vào các mô-đun. Để thu được kết quả hiệu suất chính xác, các bước sau đây liên quan đến việc tắt gỡ lỗi trong ứng dụng của bạn, vì vậy bạn nên thực hiện việc này trong bản sao làm việc cục bộ mà không thực hiện thay đổi đối với hệ thống kiểm soát nguồn của mình.

Để nhanh chóng thực hiện phép đo điểm chuẩn một lần, hãy làm như sau:

  1. Thêm thư viện vào tệp build.gradle trong mô-đun của bạn:

    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")
    }
    
  2. Để tắt tính năng gỡ lỗi trong tệp kê khai thử nghiệm, hãy cập nhật phần tử <application> để tạm thời buộc tắt tính năng gỡ lỗi:

    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"/>
    
  3. Để thêm điểm chuẩn, hãy thêm một thực thể BenchmarkRule vào tệp thử nghiệm trong thư mục androidTest. Để biết thêm thông tin về cách viết điểm chuẩn, hãy xem phần Tạo class (lớp) Microbenchmark.

    Đoạn mã sau đây cho biết cách thêm điểm chuẩn vào thử nghiệm 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();
            }
        }
    }
    

Để xem cách viết điểm chuẩn, hãy chuyển đến phần Tạo class (lớp) Microbenchmark.

Thiết lập dự án đầy đủ

Để thiết lập đo điểm chuẩn thông thường thay vì đo điểm chuẩn một lần, hãy tách các điểm chuẩn thành từng mô-đun riêng. Điều này đảm bảo rằng cấu hình của các điểm chuẩn, chẳng hạn như thiết lập debuggable thành false, được tách biệt với cấu hình thử nghiệm thông thường.

Vì Microbenchmark chạy mã của bạn trực tiếp, nên bạn cần đưa mã mà mình muốn đo điểm chuẩn vào một mô-đun Gradle riêng biệt và thiết lập phần phụ thuộc trong mô-đun đó như minh họa trong hình sau.

Cấu trúc ứng dụng với các mô-đun Gradle :app, :microbenchmark và :benchmarkable cho phép các Microbenchmark đo điểm chuẩn mã trong mô-đun :benchmarkable.

Để thêm mô-đun Gradle mới, bạn có thể dùng trình hướng dẫn mô-đun trong Android Studio. Trình hướng dẫn sẽ tạo một mô-đun được định cấu hình sẵn để đo điểm chuẩn, trong đó có một thư mục điểm chuẩn được thêm và debuggable được đặt thành false.

Bumblebee (hoặc mới hơn)

  1. Nhấp chuột phải vào dự án hoặc mô-đun trong bảng Project (Dự án) trong Android Studio và nhấp vào New (Mới) > Module (Mô-đun).
  2. Chọn Benchmark (Điểm chuẩn) trong ngăn Templates (Mẫu).
  3. Chọn loại mô-đun điểm chuẩn là Microbenchmark.
  4. Nhập microbenchmark làm tên mô-đun.
  5. Nhấp vào Finish (Hoàn tất).
  6. Định cấu hình mô-đun thư viện mới

Arctic Fox

  1. Nhấp chuột phải vào dự án hoặc mô-đun trong bảng Project (Dự án) trong Android Studio và nhấp vào New (Mới) > Module (Mô-đun).
  2. Chọn Benchmark (Điểm chuẩn) trong ngăn Templates (Mẫu).
  3. Nhập microbenchmark làm tên mô-đun.
  4. Nhấp vào Finish (Hoàn tất).
  5. Định cấu hình mô-đun thư viện mới

Sau khi tạo mô-đun, hãy thay đổi tệp build.gradle của nó và thêm testImplementation vào mô-đun có chứa mã để đo điểm chuẩn:

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"))
}

Tạo class (lớp) Microbenchmark

Điểm chuẩn là các bài kiểm thử đo lường tiêu chuẩn. Để tạo điểm chuẩn, hãy sử dụng class BenchmarkRule do thư viện cung cấp. Để đo điểm chuẩn các hoạt động, hãy dùng ActivityTestRule hoặc ActivityScenarioRule. Để đo điểm chuẩn mã giao diện người dùng, hãy dùng @UiThreadTest.

Mã dưới đây là một điểm chuẩn mẫu:

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();
        }
    }
}
    

Tắt thời gian thiết lập

Bạn có thể tắt thời gian cho các phần mã mà mình không muốn đo lường bằng block (khối) runWithTimingDisabled{}. Những phần này thường đại diện cho một số mã mà bạn cần chạy trong mỗi vòng lặp điểm chuẩn.

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));
}
    

Hãy cố gắng giảm thiểu lượng công việc thực hiện trong block measureRepeated, cũng như trong runWithTimingDisabled. BlockmeasureRepeated được chạy nhiều lần và có thể ảnh hưởng đến tổng thời gian cần thiết để chạy điểm chuẩn. Nếu cần xác minh một số kết quả điểm chuẩn, bạn có thể xác nhận kết quả cuối cùng thay vì thực hiện trong mỗi vòng lặp điểm chuẩn.

Tiến hành đo điểm chuẩn

Trong Android Studio, hãy chạy điểm chuẩn như bất kỳ @Test nào sử dụng thao tác định hướng bên cạnh class (lớp) hoặc method (phương pháp) kiểm thử của bạn, như minh họa trong hình sau.

Chạy kiểm thử Microbenchmark bằng cách sử dụng thao tác định hướng bên cạnh lớp kiểm thử

Ngoài ra, từ dòng lệnh, hãy chạy connectedCheck để thực hiện tất cả các phép kiểm thử từ mô-đun Gradle được chỉ định:

./gradlew benchmark:connectedCheck

Hoặc một phép kiểm thử đơn:

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

Kết quả đo điểm chuẩn

Sau khi chạy Microbenchmark thành công, các chỉ số sẽ hiển thị trực tiếp trong Android Studio và báo cáo điểm chuẩn đầy đủ với các chỉ số và thông tin thiết bị khác sẽ có sẵn ở định dạng JSON. Trình bổ trợ Gradle androidx.benchmark kích hoạt đầu ra JSON theo mặc định.

Kết quả microbenchmark

Theo mặc định, tệp báo cáo JSON được ghi vào ổ đĩa trên thiết bị trong thư mục nội dung nghe nhìn chia sẻ bên ngoài của APK thử nghiệm, thường nằm ở /storage/emulated/0/Android/media/app_id/app_id-benchmarkData.json.

Báo cáo JSON cũng tự động được sao chép từ thiết bị sang máy chủ lưu trữ. Các báo cáo này được viết trên máy chủ tại:

project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/app_id-benchmarkData.json

Lỗi cấu hình

Thư viện sẽ phát hiện các điều kiện sau nhằm đảm bảo dự án của bạn và môi trường được thiết lập để đạt hiệu suất chính xác:

  • Debuggable (có thể gỡ lỗi) được đặt thành false.
  • Có thiết bị vật lý đang được sử dụng (không hỗ trợ trình mô phỏng).
  • Xung nhịp đã được khóa nếu thiết bị đã bị can thiệp vào hệ thống.
  • Thiết bị có đủ mức pin cần thiết (ít nhất 25%).

Nếu có bất kỳ điều kiện nào trên đây không được đáp ứng thì điểm chuẩn sẽ báo lỗi để tránh đưa ra phép đo không chính xác.

Để loại bỏ các loại lỗi cụ thể dưới dạng cảnh báo và ngăn các lỗi này tạm dừng hoạt động đo điểm chuẩn, hãy đưa loại lỗi đó vào đối số đo lường androidx.benchmark.suppressErrors theo danh sách được phân tách bằng dấu phẩy.

Thao tác này có thể thiết lập từ tập lệnh Gradle của bạn như sau:

Groovy

android {
    defaultConfig {
       …
      testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,LOW-BATTERY"
    }
}

Kotlin

android {
    defaultConfig {
       …
      testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,LOW-BATTERY"
    }
}

Việc loại bỏ lỗi cho phép điểm chuẩn chạy ở trạng thái được định cấu hình không chính xác và tệp kết quả đầu ra của điểm chuẩn được cố ý đổi tên bằng cách đưa tên lỗi vào trước tên thử nghiệm. Ví dụ: thực hiện một điểm chuẩn có thể gỡ lỗi với tùy chọn loại bỏ lỗi trong đoạn mã phía trên sẽ thêm DEBUGGABLE_ vào trước tên thử nghiệm.