Kiểm thử hiệu suất

Android 8.0 bao gồm các bài kiểm thử hiệu suất liên kết và hwbinder để kiểm tra thông lượng và độ trễ. Mặc dù có nhiều trường hợp giúp phát hiện hiệu suất dễ nhận biết vấn đề cụ thể, việc chạy các tình huống như vậy có thể tốn thời gian và kết quả thường không khả dụng cho đến khi hệ thống được tích hợp. Sử dụng hiệu suất được cung cấp kiểm thử giúp kiểm thử dễ dàng hơn trong quá trình phát triển, phát hiện các vấn đề nghiêm trọng sớm hơn và cải thiện trải nghiệm người dùng.

Các bài kiểm thử hiệu suất gồm 4 danh mục sau:

  • thông lượng liên kết (có sẵn trong system/libhwbinder/vts/performance/Benchmark_binder.cpp)
  • độ trễ liên kết (có sẵn trong frameworks/native/libs/binder/tests/schd-dbg.cpp)
  • thông lượng hwbinder (có sẵn trong system/libhwbinder/vts/performance/Benchmark.cpp)
  • độ trễ hwbinder (có trong system/libhwbinder/vts/performance/Latency.cpp)

Giới thiệu về liên kết và hwbinder

Binder và hwbinder là giao tiếp liên quy trình (IPC) của Android các cơ sở hạ tầng có cùng trình điều khiển Linux nhưng có các đặc điểm sau khác biệt về định tính:

Tỷ lệ chất kết dính hwbinder
Mục đích Đưa ra lược đồ IPC mục đích chung cho khung Giao tiếp với phần cứng
Thuộc tính Được tối ưu hoá để sử dụng khung Android Độ trễ thấp với mức hao tổn tối thiểu
Thay đổi chính sách lên lịch cho chế độ nền trước/nền sau Không
Truyền đối số Sử dụng tính năng chuyển đổi tuần tự được đối tượng Parcel hỗ trợ Sử dụng vùng đệm tán xạ và tránh hao tổn khi sao chép dữ liệu cần thiết cho Chuyển đổi tuần tự bưu kiện
Kế thừa ưu tiên Không

Quy trình Binder và hwbinder

Trình hiển thị systrace hiển thị các giao dịch như sau:

Hình 1. Hình ảnh Systrace của liên kết khác.

Trong ví dụ trên:

  • Bốn (4) quá trình schd-dbg là các quá trình của máy khách.
  • Bốn (4) quy trình liên kết là các quy trình của máy chủ (tên bắt đầu bằng Đường viền và kết thúc bằng số thứ tự).
  • Quy trình ứng dụng luôn được ghép nối với quy trình máy chủ, vốn dành riêng cho khách hàng của mình.
  • Tất cả các cặp quy trình máy khách-máy chủ được lên lịch độc lập theo nhân đồng thời.

Trong CPU 1, nhân hệ điều hành thực thi ứng dụng để đưa ra yêu cầu. Sau đó sử dụng cùng một CPU bất cứ khi nào có thể để đánh thức quy trình máy chủ, xử lý và chuyển đổi ngữ cảnh trở lại sau khi yêu cầu hoàn tất.

Thông lượng so với độ trễ

Trong một giao dịch hoàn hảo, trong đó máy khách và quy trình máy chủ chuyển đổi liền mạch thì các thử nghiệm công suất và độ trễ không tạo ra sự khác biệt đáng kể tin nhắn. Tuy nhiên, khi nhân hệ điều hành đang xử lý yêu cầu gián đoạn (IRQ) từ phần cứng, chờ khoá hoặc chỉ đơn giản là chọn không xử lý tin nhắn thì bong bóng độ trễ có thể hình thành.

Hình 2. Bong bóng độ trễ do sự khác biệt về công suất và độ trễ.

Kiểm thử thông lượng tạo ra một số lượng lớn giao dịch với các kích thước tải trọng, cung cấp ước tính tốt về thời gian giao dịch thông thường (theo tình huống tốt nhất) và công suất tối đa mà liên kết có thể đạt được.

Ngược lại, bài kiểm thử độ trễ không thực hiện hành động nào đối với tải trọng để giảm thiểu thời gian giao dịch thông thường. Chúng ta có thể sử dụng thời gian giao dịch để ước tính liên kết chi phí đầu tư, lập số liệu thống kê cho trường hợp xấu nhất và tính tỷ lệ các giao dịch có độ trễ đáp ứng thời hạn đã chỉ định.

Xử lý đảo ngược ưu tiên

Việc đảo ngược mức độ ưu tiên xảy ra khi một luồng có mức độ ưu tiên cao hơn theo logic đang chờ một luồng có mức độ ưu tiên thấp hơn. Ứng dụng theo thời gian thực (RT) có vấn đề đảo ngược mức độ ưu tiên:

Hình 3. Đảo ngược mức độ ưu tiên theo thời gian thực .

Khi sử dụng tính năng lên lịch của Trình lập lịch biểu hoàn toàn công bằng (CFS) của Linux, một luồng luôn vẫn có cơ hội chạy ngay cả khi các luồng khác có mức độ ưu tiên cao hơn. Do đó, các ứng dụng có lập lịch CFS xử lý đảo ưu tiên như hành vi dự kiến chứ không phải là một vấn đề. Trong trường hợp khung Android cần lập lịch RT để đảm bảo đặc quyền của các luồng có mức độ ưu tiên cao, tuy nhiên, tính năng đảo ngược mức độ ưu tiên phải được giải quyết.

Ví dụ về đảo ngược ưu tiên trong giao dịch liên kết (luồng RT là bị các luồng CFS khác chặn một cách hợp lý khi chờ một luồng liên kết của bạn):

Hình 4. Đảo ngược mức độ ưu tiên, bị chặn theo thời gian thực luồng.

Để tránh bị chặn, bạn có thể sử dụng tính năng kế thừa mức độ ưu tiên để tạm thời chuyển lên cấp trên luồng Binder đến luồng RT khi luồng này phục vụ yêu cầu từ ứng dụng RT. Lưu ý rằng lịch biểu RT có tài nguyên hạn chế và nên được sử dụng một cách cẩn thận. Trong hệ thống có n CPU, số lượng RT tối đa hiện tại luồng cũng là n; các luồng RT khác có thể cần phải đợi (và do đó lỡ thời hạn) nếu tất cả CPU được các luồng RT khác sử dụng.

Để giải quyết tất cả các lần đảo ngược mức độ ưu tiên có thể xảy ra, bạn có thể sử dụng cho cả liên kết và hwbinder. Tuy nhiên, vì liên kết được sử dụng rộng rãi trên hệ thống, việc bật tính năng kế thừa ưu tiên cho các giao dịch liên kết có thể gửi nội dung rác cho hệ thống bằng nhiều luồng RT hơn khả năng phục vụ.

Chạy kiểm thử thông lượng

Quá trình kiểm thử thông lượng được chạy dựa trên thông lượng giao dịch liên kết/hwbinder. Trong một hệ thống không bị quá tải, bong bóng trễ rất hiếm và ảnh hưởng của chúng có thể loại bỏ được miễn là số lần lặp đủ cao.

  • Quá trình kiểm tra thông lượng liên kết đang ở system/libhwbinder/vts/performance/Benchmark_binder.cpp.
  • Quy trình kiểm tra thông lượng hwbinder đã ở system/libhwbinder/vts/performance/Benchmark.cpp.

Kết quả thử nghiệm

Ví dụ về kết quả kiểm tra thông lượng cho các giao dịch sử dụng nhiều tải trọng kích thước:

Benchmark                      Time          CPU           Iterations
---------------------------------------------------------------------
BM_sendVec_binderize/4         70302 ns      32820 ns      21054
BM_sendVec_binderize/8         69974 ns      32700 ns      21296
BM_sendVec_binderize/16        70079 ns      32750 ns      21365
BM_sendVec_binderize/32        69907 ns      32686 ns      21310
BM_sendVec_binderize/64        70338 ns      32810 ns      21398
BM_sendVec_binderize/128       70012 ns      32768 ns      21377
BM_sendVec_binderize/256       69836 ns      32740 ns      21329
BM_sendVec_binderize/512       69986 ns      32830 ns      21296
BM_sendVec_binderize/1024      69714 ns      32757 ns      21319
BM_sendVec_binderize/2k        75002 ns      34520 ns      20305
BM_sendVec_binderize/4k        81955 ns      39116 ns      17895
BM_sendVec_binderize/8k        95316 ns      45710 ns      15350
BM_sendVec_binderize/16k      112751 ns      54417 ns      12679
BM_sendVec_binderize/32k      146642 ns      71339 ns       9901
BM_sendVec_binderize/64k      214796 ns     104665 ns       6495
  • Thời gian cho biết độ trễ chuyến khứ hồi được đo theo thời gian thực.
  • CPU (CPU) cho biết thời gian tích luỹ khi lên lịch cho CPU cho bài kiểm thử.
  • Số lần lặp lại cho biết số lần hàm kiểm thử thực thi.

Ví dụ: đối với tải trọng 8 byte:

BM_sendVec_binderize/8         69974 ns      32700 ns      21296

... thông lượng tối đa mà liên kết có thể đạt được được tính như sau:

Thông lượng tối đa với tải trọng 8 byte = (8 * 21296)/69974 ~= 2,423 b/ns ~= 2,268 Gb/giây

Tùy chọn kiểm tra

Để nhận được kết quả trong tệp .json, hãy chạy kiểm thử bằng Đối số --benchmark_format=json:

libhwbinder_benchmark --benchmark_format=json
{
  "context": {
    "date": "2017-05-17 08:32:47",
    "num_cpus": 4,
    "mhz_per_cpu": 19,
    "cpu_scaling_enabled": true,
    "library_build_type": "release"
  },
  "benchmarks": [
    {
      "name": "BM_sendVec_binderize/4",
      "iterations": 32342,
      "real_time": 47809,
      "cpu_time": 21906,
      "time_unit": "ns"
    },
   ….
}

Chạy kiểm thử độ trễ

Bài kiểm thử độ trễ đo lường thời gian ứng dụng cần để bắt đầu khởi tạo giao dịch, chuyển sang quy trình máy chủ để xử lý, và nhận được kết quả. Kiểm thử này cũng tìm kiếm các hành vi của trình lập lịch biểu không hợp lệ đã biết có thể tác động tiêu cực đến độ trễ giao dịch, chẳng hạn như trình lập lịch biểu không hỗ trợ kế thừa kế thừa ưu tiên hoặc tuân thủ cờ đồng bộ hoá.

  • Kiểm tra độ trễ liên kết đang ở frameworks/native/libs/binder/tests/schd-dbg.cpp.
  • Đã có bài kiểm tra độ trễ hwbinder system/libhwbinder/vts/performance/Latency.cpp.

Kết quả thử nghiệm

Kết quả (ở định dạng .json) cho thấy số liệu thống kê về độ trễ trung bình/tốt nhất/ké nhất và đã quá hạn chót.

Tùy chọn kiểm tra

Kiểm thử độ trễ có các lựa chọn sau:

Lệnh Mô tả
-i value Chỉ định số lần lặp.
-pair value Chỉ định số lượng cặp quy trình.
-deadline_us 2500 Vui lòng nêu rõ thời hạn.
-v Nhận kết quả chi tiết (gỡ lỗi).
-trace Tạm dừng dấu vết khi đã đến thời hạn.

Các phần sau đây trình bày chi tiết từng tuỳ chọn, mô tả cách sử dụng và cung cấp kết quả mẫu.

Chỉ định số lần lặp lại

Ví dụ về số lượng lớn vòng lặp và đầu ra chi tiết bị tắt:

libhwbinder_latency -i 5000 -pair 3
{
"cfg":{"pair":3,"iterations":5000,"deadline_us":2500},
"P0":{"SYNC":"GOOD","S":9352,"I":10000,"R":0.9352,
  "other_ms":{ "avg":0.2 , "wst":2.8 , "bst":0.053, "miss":2, "meetR":0.9996},
  "fifo_ms": { "avg":0.16, "wst":1.5 , "bst":0.067, "miss":0, "meetR":1}
},
"P1":{"SYNC":"GOOD","S":9334,"I":10000,"R":0.9334,
  "other_ms":{ "avg":0.19, "wst":2.9 , "bst":0.055, "miss":2, "meetR":0.9996},
  "fifo_ms": { "avg":0.16, "wst":3.1 , "bst":0.066, "miss":1, "meetR":0.9998}
},
"P2":{"SYNC":"GOOD","S":9369,"I":10000,"R":0.9369,
  "other_ms":{ "avg":0.19, "wst":4.8 , "bst":0.055, "miss":6, "meetR":0.9988},
  "fifo_ms": { "avg":0.15, "wst":1.8 , "bst":0.067, "miss":0, "meetR":1}
},
"inheritance": "PASS"
}

Những kết quả kiểm tra này cho thấy những thông tin sau:

"pair":3
Tạo một cặp ứng dụng và máy chủ.
"iterations": 5000
Bao gồm 5.000 lần lặp lại.
"deadline_us":2500
Hạn chót là 2500us (2,5 mili giây); hầu hết các giao dịch dự kiến sẽ đáp ứng điều này giá trị.
"I": 10000
Một vòng lặp thử nghiệm duy nhất bao gồm hai (2) giao dịch:
  • Một giao dịch theo mức độ ưu tiên thông thường (CFS other)
  • Một giao dịch theo mức độ ưu tiên theo thời gian thực (RT-fifo)
5000 lần lặp lại tương đương với tổng cộng 10000 giao dịch.
"S": 9352
9352 giao dịch được đồng bộ hoá trong cùng một CPU.
"R": 0.9352
Cho biết tỷ lệ đồng bộ hoá giữa ứng dụng và máy chủ với nhau cùng một CPU.
"other_ms":{ "avg":0.2 , "wst":2.8 , "bst":0.053, "miss":2, "meetR":0.9996}
Trung bình (avg), kém nhất (wst) và tốt nhất (bst) cho tất cả giao dịch được phát hành bởi phương thức gọi có mức độ ưu tiên thông thường. Hạn chót để thực hiện hai giao dịch là miss, giúp tỷ lệ đáp ứng (meetR) 0,9996.
"fifo_ms": { "avg":0.16, "wst":1.5 , "bst":0.067, "miss":0, "meetR":1}
Tương tự như other_ms, nhưng dành cho các giao dịch do khách hàng phát hành bằng Mức độ ưu tiên rt_fifo. Có khả năng (nhưng không bắt buộc) là fifo_ms có kết quả tốt hơn other_ms, với điểm số thấp hơn Các giá trị avgwstmeetR cao hơn (sự khác biệt thậm chí còn đáng kể hơn khi tải trong nền).

Lưu ý: Tải trong nền có thể ảnh hưởng đến công suất kết quả và bộ dữ liệu other_ms trong kiểm thử độ trễ. Chỉ fifo_ms có thể hiển thị các kết quả tương tự miễn là tải ở chế độ nền mức độ ưu tiên thấp hơn RT-fifo.

Chỉ định giá trị cặp

Mỗi quy trình ứng dụng được ghép nối với một quy trình máy chủ dành riêng cho ứng dụng khách, và mỗi cặp có thể được lên lịch một cách độc lập cho bất kỳ CPU nào. Tuy nhiên, CPU quá trình di chuyển sẽ không diễn ra trong quá trình giao dịch miễn là cờ SYNC được honor.

Đảm bảo hệ thống không bị quá tải! Mặc dù độ trễ cao trong tình huống quá tải hệ thống như dự kiến, kết quả thử nghiệm một hệ thống quá tải không cung cấp thông tin hữu ích của bạn. Để kiểm tra một hệ thống có áp suất cao hơn, hãy dùng -pair #cpu-1 (hoặc -pair #cpu một cách thận trọng). Kiểm thử bằng -pair nn > #cpu sẽ làm quá tải phương thức và tạo ra thông tin vô ích.

Chỉ định giá trị thời hạn

Sau khi kiểm tra tình huống người dùng sâu rộng (chạy kiểm tra độ trễ trên đủ tiêu chuẩn), chúng tôi xác định rằng thời hạn phải đáp ứng là 2,5 mili giây. Cho người mới có yêu cầu cao hơn (chẳng hạn như 1000 ảnh/giây), sẽ thay đổi.

Chỉ định kết quả chi tiết

Việc sử dụng tuỳ chọn -v sẽ hiển thị kết quả chi tiết. Ví dụ:

libhwbinder_latency -i 1 -v

-------------------------------------------------- service pid: 8674 tid: 8674 cpu: 1 SCHED_OTHER 0
-------------------------------------------------- main pid: 8673 tid: 8673 cpu: 1 -------------------------------------------------- client pid: 8677 tid: 8677 cpu: 0 SCHED_OTHER 0
-------------------------------------------------- fifo-caller pid: 8677 tid: 8678 cpu: 0 SCHED_FIFO 99 -------------------------------------------------- hwbinder pid: 8674 tid: 8676 cpu: 0 ??? 99
-------------------------------------------------- other-caller pid: 8677 tid: 8677 cpu: 0 SCHED_OTHER 0 -------------------------------------------------- hwbinder pid: 8674 tid: 8676 cpu: 0 SCHED_OTHER 0
  • Luồng dịch vụ được tạo bằng một với mức độ ưu tiên SCHED_OTHER và chạy trong CPU:1 với pid 8674.
  • Giao dịch đầu tiên sau đó được bắt đầu bởi fifo-caller. Để thực hiện giao dịch này, hwbinder nâng cấp mức độ ưu tiên của máy chủ (pid: 8674 tid: 8676) là 99, đồng thời đánh dấu nó có lớp lập lịch tạm thời (được in dưới dạng ???). Bộ lập lịch sau đó đưa quy trình máy chủ vào CPU:0 để chạy và đồng bộ hoá quy trình đó với cùng một CPU với ứng dụng khách.
  • Phương thức gọi giao dịch thứ hai có Mức độ ưu tiên SCHED_OTHER. Máy chủ tự hạ cấp và phục vụ phương thức gọi có mức độ ưu tiên SCHED_OTHER.

Sử dụng dấu vết để gỡ lỗi

Bạn có thể chỉ định tuỳ chọn -trace để gỡ lỗi các vấn đề về độ trễ. Thời gian được sử dụng, bài kiểm tra độ trễ sẽ dừng bản ghi nhật ký tại thời điểm xảy ra lỗi độ trễ. Ví dụ:

atrace --async_start -b 8000 -c sched idle workq binder_driver sync freq
libhwbinder_latency -deadline_us 50000 -trace -i 50000 -pair 3
deadline triggered: halt ∓ stop trace
log:/sys/kernel/debug/tracing/trace

Các thành phần sau có thể ảnh hưởng đến độ trễ:

  • Chế độ bản dựng Android. Chế độ tiếng Anh thường chậm hơn chế độ userdebug.
  • Khung. Cách dịch vụ khung này sử dụng ioctl để định cấu hình cho liên kết?
  • Trình điều khiển Binder. Trình điều khiển có hỗ trợ thông tin chi tiết không đang khoá? Bản vá có chứa tất cả bản vá giúp thay đổi hiệu suất không?
  • Phiên bản kernel. Kernel càng có khả năng theo thời gian thực tốt hơn kết quả càng tốt.
  • Cấu hình kernel. Cấu hình nhân hệ điều hành có chứa Các cấu hình DEBUG như DEBUG_PREEMPTDEBUG_SPIN_LOCK?
  • Bộ lập lịch kernel. Hạt nhân có Nhận biết năng lượng không trình lập lịch biểu (EAS) hay trình lập lịch đa xử lý không đồng nhất (HMP)? Thực hiện bất kỳ nhân hệ điều hành nào người lái xe (cpu-freq tài xế, cpu-idle tài xế, cpu-hotplug, v.v.) ảnh hưởng đến trình lập lịch biểu?