Kiểm tra hiệu suất của ứng dụng bằng Macrobenchmark

1. Trước khi bắt đầu

Trong lớp học lập trình này, bạn sẽ tìm hiểu cách sử dụng thư viện macrobenchmark. Bạn sẽ đo lường thời gian khởi động ứng dụng, là chỉ số chính về mức độ tương tác của người dùng và thời gian kết xuất khung hình, cho biết vị trí có thể xảy ra hiện tượng giật trong ứng dụng của bạn.

Những gì bạn cần

Bạn sẽ thực hiện

  • Thêm mô-đun đo điểm chuẩn vào ứng dụng hiện có
  • Đo lường thời gian khởi động ứng dụng và kết xuất khung hình

Kiến thức bạn sẽ học được

  • Đo lường hiệu suất ứng dụng một cách đáng tin cậy

2. Thiết lập

Để bắt đầu, hãy sao chép kho lưu trữ GitHub từ dòng lệnh bằng cách sử dụng lệnh sau:

$ git clone https://github.com/googlecodelabs/android-performance.git

Ngoài ra, bạn có thể tải 2 tệp zip xuống:

Mở dự án vào trong Android Studio

  1. Trên cửa sổ Welcome to Android Studio (Chào mừng bạn đến với Android Studio), hãy chọn biểu tượng c01826594f360d94.png Open an Existing Project (Mở một dự án hiện có).
  2. Chọn thư mục [Download Location]/android-performance/benchmarking (lưu ý: nhớ chọn thư mục benchmarking có chứa build.gradle)
  3. Khi Android Studio đã nhập dự án, vui lòng đảm bảo bạn có thể chạy mô-đun app để tạo ứng dụng mẫu mà chúng tôi sẽ đo điểm chuẩn.

3. Giới thiệu về Jetpack Macrobenchmark

Thư viện Jetpack Macrobenchmark đo lường hiệu suất các tương tác lớn hơn của người dùng cuối, chẳng hạn như khởi động, tương tác với giao diện người dùng và hoạt ảnh. Thư viện cung cấp quyền kiểm soát trực tiếp đối với môi trường hiệu suất mà bạn đang kiểm thử. Nền tảng này cho phép bạn kiểm soát việc biên dịch, khởi động và dừng ứng dụng để đo lường trực tiếp quá trình khởi động trong ứng dụng, thời gian kết xuất khung hình cũng như các phần mã đã theo dõi.

Với Jetpack Macrobenchmark, bạn có thể:

  • đo lường ứng dụng nhiều lần bằng mô hình khởi chạy xác định và tốc độ cuộn
  • làm mượt phương sai hiệu suất bằng cách tính kết quả trung bình qua nhiều lần chạy kiểm thử
  • kiểm soát trạng thái biên dịch của ứng dụng – một yếu tố chính giúp đảm bảo hiệu suất ổn định
  • kiểm tra hiệu suất thực tế qua việc tái tạo cục bộ các hoạt động tối ưu hoá theo thời gian cài đặt do Cửa hàng Google Play thực hiện

Khả năng đo lường không sử dụng thư viện này với mục đích gọi trực tiếp mã ứng dụng của bạn, thay vào đó điều hướng ứng dụng dưới dạng người dùng sẽ – chạm, nhấp, vuốt, v.v. Quá trình đo được thực hiện trên thiết bị trong các hoạt động tương tác này. Nếu bạn muốn đo lường trực tiếp các phần trong mã ứng dụng, vui lòng xem nội dung bài viết Jetpack Microbenchmark.

Việc viết một điểm chuẩn cũng giống như viết một phép thử nghiệm đo lường, chỉ khác nhau ở chỗ bạn không cần phải xác minh trạng thái của ứng dụng. Điểm chuẩn này sử dụng cú pháp JUnit (@RunWith, @Rule, @Test, v.v.), nhưng các kiểm thử này chạy trong một quy trình riêng biệt cho phép khởi động lại hoặc biên dịch trước ứng dụng. Điều này giúp chúng ta chạy ứng dụng mà không phải can thiệp vào các trạng thái nội bộ của ứng dụng, theo cách thông thường người dùng sẽ làm. Chúng tôi thực hiện việc này bằng cách dùng UiAutomator để tương tác với ứng dụng đích.

Ứng dụng mẫu

Trong lớp học lập trình này, bạn sẽ làm việc với ứng dụng JetSnack mẫu. Đây là một ứng dụng đặt đồ ăn nhẹ ảo sử dụng Jetpack Compose. Để đo lường hiệu suất của ứng dụng, bạn không cần biết chi tiết về cách cấu trúc ứng dụng. Những điều bạn cần tìm hiểu là hành vi của ứng dụng và cấu trúc của giao diện người dùng để có thể truy cập các thành phần trên giao diện người dùng từ các điểm chuẩn. Chạy ứng dụng và làm quen với các màn hình cơ bản bằng cách đặt đồ ăn nhẹ mà bạn chọn.

70978a2eb7296d54.png

4. Thêm thư viện Macrobenchmark

Macrobenchmark yêu cầu thêm mô-đun Gradle mới vào dự án. Cách dễ nhất để thêm thuộc tính này vào dự án là sử dụng trình hướng dẫn mô-đun Android Studio.

Mở hộp thoại mô-đun mới (ví dụ: nhấp chuột phải vào dự án hoặc mô-đun của bạn trong bảng Dự án rồi chọn Mới > Mô-đun).

54a3ec4a924199d6.png

Chọn Điểm chuẩn từ ngăn Mẫu, vui lòng đảm bảo đã chọn Macrobenchmark làm loại mô-đun Điểm chuẩn và kiểm tra thông tin chi tiết mà bạn muốn:

Loại mô-đun điểm chuẩn Macrobenchmark được chọn.

  • Ứng dụng đích – ứng dụng sẽ được đo điểm chuẩn
  • Tên mô-đun – tên của mô-đun Gradle đo điểm chuẩn
  • Package name (tên gói) – tên gói cho các điểm chuẩn
  • SDK tối thiểu – bắt buộc phải là Android 6 (API cấp 23) trở lên

Nhấp vào Finish (Hoàn tất).

Các thay đổi do trình hướng dẫn mô-đun thực hiện

Trình hướng dẫn mô-đun thực hiện một số thay đổi đối với dự án của bạn.

Thao tác này sẽ thêm mô-đun Gradle có tên macrobenchmark (hoặc tên mà bạn đã chọn trong trình hướng dẫn). Mô-đun này sử dụng trình bổ trợ com.android.test, theo đó yêu cầu Gradle không đưa mã này vào ứng dụng của bạn, vì vậy, nó chỉ có thể chứa mã kiểm thử (hoặc điểm chuẩn).

Trình hướng dẫn cũng thực hiện các thay đổi đối với mô-đun ứng dụng mục tiêu mà bạn đã chọn. Cụ thể, trình này thêm loại bản dựng benchmark mới vào mô-đun :app của build.gradle như trong đoạn mã sau:

benchmark {
   initWith buildTypes.release
   signingConfig signingConfigs.debug
   matchingFallbacks = ['release']
   debuggable false
}

Loại buildType này sẽ mô phỏng release buildType của bạn giống nhất có thể. Sự khác biệt so với release buildType là signingConfig được đặt thành debug, chỉ cần thiết để bạn có thể xây dựng ứng dụng cục bộ mà không yêu cầu kho khóa sản xuất.

Tuy nhiên, vì cờ debuggable bị vô hiệu hoá nên trình hướng dẫn sẽ thêm thẻ <profileable> vào AndroidManifest.xml nhằm cho phép các điểm chuẩn lập hồ sơ ứng dụng của bạn bằng hiệu suất của bản phát hành.

<application>

  <profileable
     android:shell="true"
     tools:targetApi="q" />

</application>

Để biết thêm thông tin chi tiết về nội dung <profileable>, vui lòng xem tài liệu của chúng tôi.

Điều cuối cùng mà trình hướng dẫn này cần làm là tạo một scaffold để chuẩn hoá thời gian khởi động (chúng ta sẽ thực hiện việc này ở bước tiếp theo).

Bây giờ, bạn đã có thể bắt đầu viết các điểm chuẩn.

5. Đo lường khả năng khởi động của ứng dụng

Thời gian khởi động ứng dụng hoặc thời gian người dùng cần để bắt đầu sử dụng ứng dụng, là chỉ số chính ảnh hưởng đến mức độ tương tác của người dùng. Trình hướng dẫn mô-đun tạo một lớp kiểm thử ExampleStartupBenchmark có khả năng đo lường thời gian khởi động ứng dụng và sẽ có dạng như sau:

@RunWith(AndroidJUnit4::class)
class ExampleStartupBenchmark {
   @get:Rule
   val benchmarkRule = MacrobenchmarkRule()

   @Test
   fun startup() = benchmarkRule.measureRepeated(
       packageName = "com.example.macrobenchmark_codelab",
       metrics = listOf(StartupTimingMetric()),
       iterations = 5,
       startupMode = StartupMode.COLD,
   ){
        pressHome()
        startActivityAndWait()
   }
}

Các tham số có ý nghĩa gì?

Khi viết một điểm chuẩn, điểm truy cập là hàm measureRepeated của MacrobenchmarkRule. Hàm này xử lý mọi vấn đề liên quan đến điểm chuẩn, nhưng bạn cần chỉ định các tham số sau:

  • packageName – Điểm chuẩn này chạy trong một quy trình riêng biệt với ứng dụng đang trong quá trình thử nghiệm, vì thế bạn cần chỉ định ứng dụng nào sẽ đo lường.
  • metrics – Loại thông tin bạn muốn đo lường trong lúc đo điểm chuẩn. Trong trường hợp này, chúng ta quan tâm đến thời gian khởi động ứng dụng. Vui lòng xem tài liệu để biết các loại chỉ số khác.
  • iterations – Số lần lặp lại điểm chuẩn. Càng nhiều vòng lặp thì kết quả càng ổn định, nhưng đồng thời cũng mất nhiều thời gian thực thi hơn. Con số lý tưởng sẽ phụ thuộc vào mức độ dao động của chỉ số cụ thể này đối với ứng dụng của bạn.
  • startupMode – Cho phép bạn xác định cách ứng dụng được khởi động khi bắt đầu đo điểm chuẩn. COLD, WARMHOT hiện có sẵn. Chúng tôi sử dụng COLD, vì đây là khối lượng tác vụ lớn nhất mà ứng dụng phải thực hiện.
  • measureBlock (tham số lambda cuối cùng) – Trong hàm này, bạn xác định những hành động mà bạn muốn đo lường trong điểm chuẩn (bắt đầu từ một Hoạt động, nhấp vào các thành phần giao diện người dùng, cuộn, vuốt, v.v.) và macrobenchmark sẽ thu thập metrics đã xác định trong khối này.

Cách viết các thao tác đo điểm chuẩn

Macrobenchmark sẽ cài đặt và khởi động lại ứng dụng. Vui lòng đảm bảo bạn viết các hoạt động tương tác độc lập với trạng thái của ứng dụng. Macrobenchmark cung cấp một số chức năng hữu ích và tham số để tương tác với ứng dụng của bạn.

Quan trọng nhất vẫn là hàm startActivityAndWait(). Hàm này sẽ khởi đầu Hoạt động mặc định và đợi cho đến lúc khung đầu tiên hiển thị trước khi tiếp tục các hướng dẫn đo điểm chuẩn của bạn. Nếu muốn bắt đầu một Hoạt động khác hoặc điều chỉnh Ý định bắt đầu, bạn có thể sử dụng tham số intent hoặc block (không bắt buộc).

Một hàm hữu ích khác phải kể đến là pressHome(). Hàm này cho phép đặt lại điểm chuẩn về điều kiện cơ bản trong trường hợp bạn không tắt ứng dụng của mình cho mỗi lần lặp lại (chẳng hạn như khi bạn sử dụng StartupMode.HOT).

Đối với bất kỳ hoạt động tương tác nào khác, bạn cũng có thể sử dụng tham số device để tìm các thành phần trên giao diện người dùng, cuộn, đợi một số nội dung, v.v.

Tốt rồi, giờ chúng ta đã xác định được điểm chuẩn khi khởi động, bạn có thể chạy phép đo điểm chuẩn này trong bước tiếp theo.

6. Chạy phép đo điểm chuẩn

Trước khi chạy thử nghiệm phép đo điểm chuẩn, hãy đảm bảo bạn đã chọn đúng biến thể bản dựng trong Android Studio:

  1. Chọn bảng Biến thể bản dựng
  2. Thay đổi Biến thể bản dựng đang hoạt động thành benchmark
  3. Đợi Android Studio đồng bộ hóa

b8a622b5a347e9f3.gif

Nếu bạn không thực hiện thao tác này, việc đo điểm chuẩn trong thời gian chạy sẽ không thành công với thông báo lỗi cho biết bạn không nên đo điểm chuẩn cho ứng dụng debuggable:

java.lang.AssertionError: ERRORS (not suppressed): DEBUGGABLE
WARNINGS (suppressed):

ERROR: Debuggable Benchmark
Benchmark is running with debuggable=true, which drastically reduces
runtime performance in order to support debugging features. Run
benchmarks with debuggable=false. Debuggable affects execution speed
in ways that mean benchmark improvements might not carry over to a
real user's experience (or even regress release performance).

Bạn tạm thời có thể ngăn lỗi này bằng đối số đo lường androidx.benchmark.suppressErrors = "DEBUGGABLE". Bạn có thể làm theo các bước tương tự như trong hướng dẫn Chạy phép đo điểm chuẩn trên Trình mô phỏng Android.

Giờ đây, bạn đã có thể chạy phép đo điểm chuẩn giống như cách chạy kiểm thử nghiệm đo lường. Bạn có thể chạy hàm kiểm thử hoặc các lớp bằng biểu tượng máng xối bên cạnh.

e72cc74b6fecffdb.png

Vui lòng đảm bảo bạn đã chọn thiết bị thực, vì việc chạy phép đo điểm chuẩn trên trình mô phỏng Android sẽ không thành công trong thời gian chạy nếu có cảnh báo về kết quả không chính xác. Mặc dù về mặt kỹ thuật, bạn có thể chạy trên trình mô phỏng, nhưng về cơ bản, bạn đang đo lường hiệu suất của máy chủ – nếu quá tải, phép đo điểm chuẩn của bạn sẽ hoạt động chậm hơn và ngược lại.

e28a1ff21e9b45b4.png

Sau khi chạy phép đo điểm chuẩn, ứng dụng sẽ được tạo lại và sau đó sẽ chạy phép đo điểm chuẩn của bạn. Việc đo điểm chuẩn sẽ bắt đầu, dừng và thậm chí là cài đặt lại ứng dụng của bạn nhiều lần dựa trên iterations bạn đã xác định.

7. (Không bắt buộc) Chạy phép đo điểm chuẩn trên Trình mô phỏng Android

Nếu không có thiết bị thực nhưng vẫn muốn chạy phép đo điểm chuẩn, bạn có thể chặn lỗi thời gian chạy bằng đối số đo lường androidx.benchmark.suppressErrors = "EMULATOR"

Để chặn lỗi, hãy chỉnh sửa cấu hình chạy của bạn:

  1. Chọn chế độ "Edit Configurations..." (Chỉnh sửa cấu hình) trong trình đơn chạy: 354500cd155dec5b.png
  2. Trong cửa sổ mở ra, hãy chọn biểu tượng "tùy chọn" d628c071dd2bf454.png bên cạnh "Đối số đo lường" a4c3519e48f4ac55.png
  3. Thêm tham số đo lường bổ sung bằng cách nhấp vào biểu tượng ➕ và nhập thông tin chi tiết a06c7f6359d6b92c.png
  4. Xác nhận lựa chọn bằng cách nhấp vào OK. Bạn sẽ thấy đối số ở hàng "Đối số đo lường" c30baf54c420ed79.png
  5. Xác nhận cấu hình Chạy bằng cách nhấp vào Ok.

Ngoài ra, nếu cần đặt vĩnh viễn mã này trong cơ sở mã của mình, bạn có thể thực hiện việc đó từ build.gradle trong mô-đun :macrobenchmark:

defaultConfig {
    // ...
    testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = 'EMULATOR'
}

8. Tìm hiểu kết quả khởi động

Sau khi chạy xong, phép đo điểm chuẩn sẽ cung cấp cho bạn kết quả trực tiếp trong Android Studio như ở ảnh chụp màn hình bên dưới:

f934731d29dcd25c.png

Bạn có thể thấy trong trường hợp này, thời gian khởi động trên Google Pixel 7 có giá trị tối thiểu là 294,8 mili giây, trung bình là 301,5 mili giây và tối đa là 314,8 mili giây. Lưu ý là trên thiết bị của mình, bạn có thể nhận được kết quả khác nhau khi chạy cùng một phép đo điểm chuẩn. Một số yếu tố có thể ảnh hưởng đến kết quả, chẳng hạn như:

  • cấu hình của thiết bị
  • phiên bản mà hệ thống sử dụng
  • các ứng dụng đang chạy trong nền

Theo đó, điều quan trọng là cần so sánh các kết quả trên cùng một thiết bị, tốt nhất là ở cùng một trạng thái, nếu không bạn có thể thấy sự khác biệt lớn. Nếu không thể đảm bảo trạng thái tương đương, bạn nên tăng số lần iterations để xử lý các kết quả ngoại lệ.

Để tạo điều kiện cho việc điều tra, thư viện Macrobenchmark sẽ ghi lại hoạt động theo dõi hệ thống trong quá trình thực thi các phép đo điểm chuẩn. Để thuận tiện, Android Studio sẽ đánh dấu mỗi lần lặp lại, đồng thời các dấu thời gian đo được đều liên kết đến hệ thống theo dõi, giúp bạn dễ dàng mở ra để điều tra.

9. (Bài tập không bắt buộc) Khai báo khi ứng dụng của bạn đã sẵn sàng sử dụng

Macrobenchmark có thể tự động đo thời gian đến khung hình đầu tiên do ứng dụng của bạn hiển thị (timeToInitialDisplay). Tuy nhiên, nội dung của ứng dụng thường không hoàn tất tải cho đến khi khung hình đầu tiên hiển thị, đồng thời bạn nên biết người dùng phải chờ bao lâu để có thể dùng ứng dụng. Thời gian đó là thời gian hiển thị toàn bộ – khi ứng dụng tải đầy đủ nội dung và người dùng có thể tương tác với ứng dụng. Thư viện Macrobenchmark có thể tự động phát hiện dấu thời gian này, nhưng bạn cần phải điều chỉnh ứng dụng để biết thời điểm xảy ra với hàm Activity.reportFullyDrawn().

Mẫu này cho thấy thanh tiến trình đơn giản cho đến khi dữ liệu được tải, vì thế, bạn nên chờ đến khi dữ liệu sẵn sàng cũng như danh sách các món ăn nhẹ được sắp xếp và vẽ. Vui lòng điều chỉnh ứng dụng mẫu và thêm lệnh gọi reportFullyDrawn().

Mở tệp Feed.kt trong gói .ui.home từ ngăn Dự án.

800f7390ca53998d.png

Trong tệp đó, bạn sẽ tìm thành phần kết hợp SnackCollectionList chịu trách nhiệm soạn danh sách các món ăn nhẹ.

Bạn cần kiểm tra dữ liệu đã sẵn sàng. Lưu ý là cho đến khi nội dung sẵn sàng, bạn sẽ nhận được một danh sách trống từ tham số ​​snackCollections, vì vậy, bạn có thể sử dụng thành phần kết hợp ReportDrawnWhen để xử lý báo cáo sau khi thuộc tính là đúng.

ReportDrawnWhen { snackCollections.isNotEmpty() }

Box(modifier) {
   LazyColumn {
   // ...
}

Ngoài ra, bạn cũng có thể sử dụng thành phần kết hợp ReportDrawnAfter{} chấp nhận hàm suspend và đợi cho đến khi hàm này hoàn tất. Bằng cách này, bạn có thể đợi một số dữ liệu được tải không đồng bộ hoặc một số ảnh động hoàn tất.

Khi đã thực hiện xong, bạn cần điều chỉnh ExampleStartupBenchmark để chờ nội dung. Nếu không, phép đo điểm chuẩn sẽ kết thúc với khung hình được kết xuất đầu tiên và có thể bỏ qua chỉ số này.

Điểm chuẩn khởi động hiện tại chỉ đợi khung hiển thị đầu tiên. Lệnh đợi này sẽ được đưa vào hàm startActivityAndWait().

@Test
fun startup() = benchmarkRule.measureRepeated(
   packageName = "com.example.macrobenchmark_codelab",
   metrics = listOf(StartupTimingMetric()),
   iterations = 5,
   startupMode = StartupMode.COLD,
) {
   pressHome()
   startActivityAndWait()

   // TODO wait until content is ready
}

Trong trường hợp này, bạn có thể đợi cho đến khi danh sách nội dung có một số phần tử con, sau đó hãy thêm wait() như trong đoạn mã sau:

@Test
fun startup() = benchmarkRule.measureRepeated(
   //...
) {
   pressHome()
   startActivityAndWait()

   val contentList = device.findObject(By.res("snack_list"))
   val searchCondition = Until.hasObject(By.res("snack_collection"))
   // Wait until a snack collection item within the list is rendered
   contentList.wait(searchCondition, 5_000)
}

Giải thích những gì sẽ xảy ra trong đoạn mã:

  1. Chúng ta tìm thấy danh sách đồ ăn nhẹ nhờ Modifier.testTag("snack_list")
  2. Chúng ta xác định điều kiện tìm kiếm trong đó sử dụng snack_collection dưới dạng phần tử để chờ
  3. Chúng ta dùng hàm UiObject2.wait để đợi điều kiện bên trong đối tượng giao diện người dùng với thời gian chờ là 5 giây

Bạn hiện đã có thể chạy lại phép đo điểm chuẩn, đồng thời thư viện sẽ tự động đo lường timeToInitialDisplaytimeToFullDisplay như trong ảnh chụp màn hình dưới đây:

3655d7199e4f678b.png

Bạn có thể thấy sự khác biệt giữa TTID và TTFD trong trường hợp này là 413 mili giây. Điều này có nghĩa là mặc dù người dùng thấy khung hình đầu tiên hiển thị trong 319,4 mili giây, nhưng họ sẽ không thể cuộn danh sách để xem thêm 413 mili giây.

10. Thời gian kết xuất khung hình chuẩn

Sau khi người dùng truy cập ứng dụng, chỉ số thứ hai họ gặp sẽ nói lên độ mượt của ứng dụng. Hoặc trong trường hợp này, ứng dụng có bỏ bất kỳ khung hình nào hay không. Để đo lường, chúng ta sẽ sử dụng FrameTimingMetric.

Giả sử bạn muốn đo hành vi cuộn của danh sách các mục mà không muốn đo lường bất kỳ mục nào khác trước tình huống đó. Bạn cần chia điểm chuẩn thành các lượt tương tác được đo lường và không được đo lường. Để làm việc đó, chúng ta sẽ dùng tham số của hàm lambda setupBlock.

Trong các lượt tương tác chưa được đo lường (đã xác định ở setupBlock), chúng ta sẽ bắt đầu Hoạt động mặc định. Và trong các lượt tương tác được đo lường (đã xác định ở measureBlock), chúng ta sẽ tìm phần tử danh sách giao diện người dùng, cuộn danh sách và đợi cho đến khi màn hình hiển thị nội dung. Nếu không chia các lượt tương tác thành hai phần, bạn sẽ không thể phân biệt được khung hình nào đã tạo trong quá trình khởi động ứng dụng và khung hình nào đã tạo trong quá trình cuộn danh sách.

Tạo điểm chuẩn về thời gian kết xuất khung hình

Để đạt được quy trình nói trên, hãy tạo một lớp ScrollBenchmarks mới bằng thử nghiệm scroll() có chứa điểm chuẩn của thời gian kết xuất khung hình cuộn. Trước tiên, bạn tạo lớp thử nghiệm với quy tắc điểm chuẩn và phương pháp thử nghiệm trống:

@RunWith(AndroidJUnit4::class)
class ScrollBenchmarks {
   @get:Rule
   val benchmarkRule = MacrobenchmarkRule()

   @Test
   fun scroll() {
       // TODO implement scrolling benchmark
   }
}

Sau đó, vui lòng thêm khung chuẩn với các tham số bắt buộc.

@Test
fun scroll() {
   benchmarkRule.measureRepeated(
       packageName = "com.example.macrobenchmark_codelab",
       iterations = 5,
       metrics = listOf(FrameTimingMetric()),
       startupMode = StartupMode.COLD,
       setupBlock = {
           // TODO Add not measured interactions.
       }
   ) {
       // TODO Add interactions to measure list scrolling.
   }
}

Điểm chuẩn này sẽ sử dụng cùng tham số với điểm chuẩn startup, ngoại trừ tham số metricssetupBlock. FrameTimingMetric thu thập dấu thời gian của khung hình do ứng dụng hiện tại tạo ra.

Giờ thì bạn hãy điền vào setupBlock. Như đã đề cập trước đó, các lượt tương tác không được đo lường theo điểm chuẩn trong hàm lambda này. Bạn có thể sử dụng khối này chỉ để mở ứng dụng và đợi khung đầu tiên hiển thị.

@Test
fun scroll() {
   benchmarkRule.measureRepeated(
       packageName = "com.example.macrobenchmark_codelab",
       iterations = 5,
       metrics = listOf(FrameTimingMetric()),
       startupMode = StartupMode.COLD,
       setupBlock = {
           // Start the default activity, but don't measure the frames yet
           pressHome()
           startActivityAndWait()
       }
   ) {
       // TODO Add interactions to measure list scrolling.
   }
}

Và bây giờ, hãy viết measureBlock (tham số hàm lambda cuối cùng). Đầu tiên, vì thao tác gửi các mục đến danh sách đồ ăn nhẹ không đồng bộ, bạn nên đợi cho đến khi nội dung sẵn sàng.

benchmarkRule.measureRepeated(
   // ...
) {
    val contentList = device.findObject(By.res("snack_list"))

    val searchCondition = Until.hasObject(By.res("snack_collection"))
    // Wait until a snack collection item within the list is rendered
    contentList.wait(searchCondition, 5_000)

   // TODO Scroll the list
}

Nếu không muốn đo lường chế độ thiết lập bố cục ban đầu, bạn có thể chờ cho nội dung sẵn sàng trong setupBlock.

Tiếp theo, đặt lề cho cử chỉ vào danh sách đồ ăn nhẹ. Bạn cần phải thực hiện việc này vì nếu không ứng dụng có thể kích hoạt thao tác điều hướng của hệ thống và rời khỏi ứng dụng thay vì cuộn nội dung.

benchmarkRule.measureRepeated(
   // ...
) {
   val contentList = device.findObject(By.res("snack_list"))

   val searchCondition = Until.hasObject(By.res("snack_collection"))
   // Wait until a snack collection item within the list is rendered
   contentList.wait(searchCondition, 5_000)

   // Set gesture margin to avoid triggering system gesture navigation
   contentList.setGestureMargin(device.displayWidth / 5)

   // TODO Scroll the list
}

Sau cùng hãy cuộn danh sách bằng cử chỉ fling() (bạn cũng có thể sử dụng scroll() hoặc swipe() tuỳ thuộc vào tốc độ cuộn mong muốn) và đợi đến khi giao diện người dùng chuyển sang trạng thái rảnh.

benchmarkRule.measureRepeated(
   // ...
) {
   val contentList = device.findObject(By.res("snack_list"))

   val searchCondition = Until.hasObject(By.res("snack_collection"))
   // Wait until a snack collection item within the list is rendered
   contentList.wait(searchCondition, 5_000)

   // Set gesture margin to avoid triggering gesture navigation
   contentList.setGestureMargin(device.displayWidth / 5)

   // Scroll down the list
   contentList.fling(Direction.DOWN)

   // Wait for the scroll to finish
   device.waitForIdle()
}

Thư viện sẽ đo dấu thời gian của khung hình do ứng dụng tạo ra khi thực hiện các hành động đã xác định.

Giờ thì bạn đã có phép đo điểm chuẩn để chạy.

Chạy phép đo điểm chuẩn

Bạn có thể chạy phép đo điểm chuẩn tương tự như điểm chuẩn khởi động. Nhấp vào biểu tượng máng xối bên cạnh thử nghiệm và chọn Chạy 'scroll()'.

30043f8d11fec372.png

Nếu bạn cần thêm thông tin về cách chạy phép đo điểm chuẩn, vui lòng xem bước Chạy phép đo điểm chuẩn.

Tìm hiểu các kết quả

FrameTimingMetric xuất ra thời lượng khung hình tính bằng mili giây (frameDurationCpuMs) ở phân vị thứ 50, 90, 95 và 99. Trên Android 12 (API cấp 31) trở lên, thiết bị này cũng sẽ trả về thời lượng khung hình vượt quá giới hạn (frameOverrunMs). Giá trị này có thể là số âm, nghĩa là bạn vẫn còn thời gian để tạo khung.

2e02ba58e1b882bc.png

Từ kết quả, bạn có thể thấy giá trị trung bình (P50) để tạo khung hình trên Google Pixel 7 là 3,8 mili giây, tức là dưới 6,4 mili giây trong giới hạn thời gian kết xuất khung hình. Ngoài ra, có thể đã có một số khung hình bị bỏ qua trong phân vị trên 99 (P99 ), vì khung hình mất 35,7 mili giây để tạo, nghĩa là đã vượt quá giới hạn 33,2 mili giây.

Tương tự như kết quả khởi động ứng dụng, bạn có thể nhấp vào iteration để mở nội dung hệ thống theo dõi ghi lại trong quá trình đo điểm chuẩn và điều tra các thành phần đóng góp vào dấu thời gian thu được.

11. Xin chúc mừng

Chúc mừng bạn đã hoàn thành lớp học lập trình về cách đo lường hiệu suất bằng Jetpack Macrobenchmark!

Tiếp theo là gì?

Hãy tham khảo lớp học lập trình Cải thiện hiệu suất của ứng dụng thông qua Hồ sơ cơ sở. Ngoài ra, vui lòng kiểm tra kho lưu trữ GitHub về mẫu hiệu suất có chứa Macrobenchmark và các mẫu hiệu suất khác.

Tài liệu tham khảo