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 | Có | 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 | Có |
Quy trình Binder và hwbinder
Trình hiển thị systrace hiển thị các giao dịch như sau:
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.
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:
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):
Để 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
)
- Một giao dịch theo mức độ ưu tiên thông thường (
"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ênrt_fifo
. Có khả năng (nhưng không bắt buộc) làfifo_ms
có kết quả tốt hơnother_ms
, với điểm số thấp hơn Các giá trịavg
vàwst
vàmeetR
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 n
có n > #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 trongCPU:1
vớipid 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àoCPU: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ênSCHED_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_PREEMPT
vàDEBUG_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?