Viết một Microbenchmark

Để tìm hiểu cách sử dụng thư viện Microbenchmark bằng cách thêm các thay đổi vào mã xử lý ứng dụng của bạn, hãy xem phần Bắt đầu nhanh. Để tìm hiểu cách hoàn tất quá trình thiết lập đầy đủ với các thay đổi phức tạp hơn cho cơ sở mã của bạn, hãy xem phần Thiết lập dự án đầy đủ.

Bắt đầu nhanh

Phần này trình bày 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 cần 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 tính năng gỡ lỗi trong ứng dụng của bạn. Vì vậy, hãy thực hiện việc này trong bản sao làm việc cục bộ mà không sửa đổi hệ thống kiểm soát nguồn của mình.

Để 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 hoặc build.gradle.kts trong mô-đun của bạn:

    project_root/module_dir/build.gradle.kts

    Kotlin

    dependencies {
        androidTestImplementation("androidx.benchmark:benchmark-junit4:1.2.1")
    }
    

    Groovy

    dependencies {
        androidTestImplementation 'androidx.benchmark:benchmark-junit4:1.2.1'
    }
    
  2. Cập nhật tạm thời phần tử <application> để buộc tắt tính năng gỡ lỗi trong tệp kê khai kiểm thử:

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

    Đoạn mã sau đây cho biết cách thêm điểm chuẩn vào một hoạt động kiểm thử đo lường:

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

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

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

Để thiết lập việc đ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 giúp đảm bảo rằng cấu hình của các điểm chuẩn, chẳng hạn như đặt debuggable thành false, được tách biệt với các bài kiểm thử thông thường.

Vì Microbenchmark chạy mã trực tiếp, nên hãy đặt mã bạn 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 trên mô-đun đó như minh hoạ trong hình 1.

cấu trúc ứng dụng
Hình 1. Cấu trúc ứng dụng với các mô-đun Gradle :app, :microbenchmark: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.

  1. Nhấp chuột phải vào dự án hoặc mô-đun của bạn trong bảng điều khiển Project (Dự án) trong Android Studio rồi nhấp vào New > Module (Mới > 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).

Định cấu hình mô-đun thư viện mới
Hình 2. Thêm mô-đun Gradle mới trong Android Studio Bumblebee.

Sau khi tạo mô-đun, hãy thay đổi tệp build.gradle hoặc build.gradle.kts rồi thêm androidTestImplementation vào mô-đun chứa mã để đo điểm chuẩn:

Kotlin

dependencies {
    // The module name might be different.
    androidTestImplementation(project(":benchmarkable"))
}

Groovy

dependencies {
    // The module name might be different.
    androidTestImplementation project(':benchmarkable')
}

Tạo 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 lớp BenchmarkRule do thư viện cung cấp. Để đo điểm chuẩn các hoạt động, hãy dùng ActivityScenario 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 lần lặp lại của đ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() {
    // 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));
}
    

Hãy cố gắng giảm thiểu lượng công việc thực hiện bên trong khối measureRepeated, cũng như trong runWithTimingDisabled. Khối measureRepeated đượ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, thì bạn có thể xác nhận kết quả cuối cùng thay vì thực hiện trong mỗi lần lặp lại của đ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 lớp hoặc phương thức kiểm thử của bạn, như minh hoạ trong hình 3.

Chạy Microbenchmark
Hình 3. 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ị ngay trong Android Studio và báo cáo đầy đủ về điểm chuẩn có thông tin bổ sung về thiết bị và chỉ số sẽ có sẵn ở định dạng JSON.

Kết quả Microbenchmark
Hình 4. Kết quả Microbenchmark.

Các báo cáo JSON và mọi dấu vết lập hồ sơ cũng được tự động sao chép từ thiết bị sang máy chủ lưu trữ. Những nội dung này được ghi trên máy chủ lưu trữ tại vị trí sau:

project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/

Theo mặc định, báo cáo JSON được ghi vào ổ đĩa trên thiết bị trong thư mục phương tiện được chia sẻ bên ngoài của APK kiểm thử, thường đặt trong /storage/emulated/0/Android/media/**app_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ị thực đang được sử dụng (không hỗ trợ trình mô phỏng).
  • Xung nhịp đã được khoá 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 là 25%.

Nếu có lượt kiểm tra nào trước đó không thành công, thì điểm chuẩn sẽ báo lỗi để không khuyến khích đo lường 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 chuyển loại lỗi trong danh sách được phân tách bằng dấu phẩy cho đối số đo lường androidx.benchmark.suppressErrors.

Bạn có thể thiết lập tuỳ chọn này từ tập lệnh Gradle như trong ví dụ sau:

Kotlin

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

Groovy

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

Bạn cũng có thể loại bỏ các lỗi bằng dòng lệnh:

$ ./gradlew :benchmark:connectedCheck -P andoidtestInstrumentationRunnerArguments.androidx.benchmark.supperssErrors=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à kết quả đầu ra của điểm chuẩn được đổi tên có chủ đích bằng cách đưa tên lỗi vào trước tên phép kiểm thử. Ví dụ: tiến hành đo điểm chuẩn có thể gỡ lỗi với tuỳ 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 phép kiểm thử.