Android 8.0 menyertakan pengujian kinerja binder dan hwbinder untuk throughput dan latensi. Sementara banyak skenario yang ada untuk mendeteksi masalah kinerja yang terlihat, menjalankan skenario tersebut dapat memakan waktu dan hasil sering tidak tersedia sampai setelah sistem terintegrasi. Menggunakan tes kinerja yang disediakan memudahkan pengujian selama pengembangan, mendeteksi masalah serius lebih awal, dan meningkatkan pengalaman pengguna.
Tes kinerja mencakup empat kategori berikut:
- throughput pengikat (tersedia di
system/libhwbinder/vts/performance/Benchmark_binder.cpp
) - latensi pengikat (tersedia di
frameworks/native/libs/binder/tests/schd-dbg.cpp
) - throughput hwbinder (tersedia di
system/libhwbinder/vts/performance/Benchmark.cpp
) - hwbinder latency (tersedia di
system/libhwbinder/vts/performance/Latency.cpp
)
Tentang binder dan hwbinder
Binder dan hwbinder adalah infrastruktur komunikasi antar proses (IPC) Android yang berbagi driver Linux yang sama tetapi memiliki perbedaan kualitatif berikut:
Aspek | bahan pengikat | pengikat |
---|---|---|
Tujuan | Menyediakan skema IPC tujuan umum untuk kerangka kerja | Berkomunikasi dengan perangkat keras |
Properti | Dioptimalkan untuk penggunaan kerangka kerja Android | Latensi rendah overhead minimum |
Ubah kebijakan penjadwalan untuk latar depan/latar belakang | Ya | Tidak |
Argumen berlalu | Menggunakan serialisasi yang didukung oleh objek Parcel | Menggunakan buffer pencar dan menghindari overhead untuk menyalin data yang diperlukan untuk serialisasi Paket |
Warisan prioritas | Tidak | Ya |
Proses pengikat dan hwbinder
Visualisator systrace menampilkan transaksi sebagai berikut:
Dalam contoh di atas:
- Empat (4) proses schd-dbg adalah proses klien.
- Empat (4) proses pengikat adalah proses server (nama dimulai dengan Binder dan diakhiri dengan nomor urut).
- Proses klien selalu dipasangkan dengan proses server, yang didedikasikan untuk kliennya.
- Semua pasangan proses client-server dijadwalkan secara independen oleh kernel secara bersamaan.
Di CPU 1, kernel OS mengeksekusi klien untuk mengeluarkan permintaan. Kemudian menggunakan CPU yang sama bila memungkinkan untuk membangunkan proses server, menangani permintaan, dan beralih konteks kembali setelah permintaan selesai.
Throughput vs. latensi
Dalam transaksi yang sempurna, di mana proses klien dan server beralih dengan mulus, pengujian throughput dan latensi tidak menghasilkan pesan yang berbeda secara substansial. Namun, ketika kernel OS menangani permintaan interupsi (IRQ) dari perangkat keras, menunggu kunci, atau hanya memilih untuk tidak segera menangani pesan, gelembung latensi dapat terbentuk.
Tes throughput menghasilkan sejumlah besar transaksi dengan ukuran muatan yang berbeda, memberikan perkiraan yang baik untuk waktu transaksi reguler (dalam skenario kasus terbaik) dan throughput maksimum yang dapat dicapai pengikat.
Sebaliknya, uji latensi tidak melakukan tindakan pada payload untuk meminimalkan waktu transaksi reguler. Kita dapat menggunakan waktu transaksi untuk memperkirakan overhead pengikat, membuat statistik untuk kasus terburuk, dan menghitung rasio transaksi yang latensinya memenuhi tenggat waktu yang ditentukan.
Menangani inversi prioritas
Pembalikan prioritas terjadi ketika utas dengan prioritas lebih tinggi secara logis menunggu utas dengan prioritas lebih rendah. Aplikasi real-time (RT) memiliki masalah inversi prioritas:
Saat menggunakan penjadwalan Linux Completely Fair Scheduler (CFS), utas selalu memiliki peluang untuk berjalan bahkan ketika utas lain memiliki prioritas lebih tinggi. Akibatnya, aplikasi dengan penjadwalan CFS menangani inversi prioritas sebagai perilaku yang diharapkan dan bukan sebagai masalah. Namun, dalam kasus di mana kerangka kerja Android memerlukan penjadwalan RT untuk menjamin hak istimewa utas prioritas tinggi, inversi prioritas harus diselesaikan.
Contoh inversi prioritas selama transaksi pengikat (utas RT secara logis diblokir oleh utas CFS lainnya saat menunggu utas pengikat untuk diservis):
Untuk menghindari penyumbatan, Anda dapat menggunakan pewarisan prioritas untuk sementara mengeskalasi utas pengikat ke utas RT saat melayani permintaan dari klien RT. Ingatlah bahwa penjadwalan RT memiliki sumber daya yang terbatas dan harus digunakan dengan hati-hati. Dalam sistem dengan n CPU, jumlah maksimum thread RT saat ini juga n ; utas RT tambahan mungkin perlu menunggu (dan dengan demikian melewatkan tenggat waktunya) jika semua CPU diambil oleh utas RT lainnya.
Untuk menyelesaikan semua kemungkinan inversi prioritas, Anda dapat menggunakan pewarisan prioritas untuk binder dan hwbinder. Namun, karena pengikat digunakan secara luas di seluruh sistem, mengaktifkan pewarisan prioritas untuk transaksi pengikat mungkin mengirim spam ke sistem dengan lebih banyak utas RT daripada yang dapat dilayaninya.
Menjalankan tes throughput
Tes throughput dijalankan terhadap throughput transaksi binder/hwbinder. Dalam sistem yang tidak kelebihan beban, gelembung latensi jarang terjadi dan dampaknya dapat dihilangkan selama jumlah iterasi cukup tinggi.
- Tes throughput pengikat ada di
system/libhwbinder/vts/performance/Benchmark_binder.cpp
. - Tes throughput hwbinder ada di
system/libhwbinder/vts/performance/Benchmark.cpp
.
Hasil tes
Contoh hasil pengujian throughput untuk transaksi yang menggunakan ukuran payload yang berbeda:
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
- Waktu menunjukkan penundaan perjalanan pulang pergi yang diukur secara real time.
- CPU menunjukkan akumulasi waktu ketika CPU dijadwalkan untuk pengujian.
- Iterasi menunjukkan berapa kali fungsi pengujian dijalankan.
Misalnya, untuk muatan 8 byte:
BM_sendVec_binderize/8 69974 ns 32700 ns 21296
… throughput maksimum yang dapat dicapai pengikat dihitung sebagai:
Throughput MAX dengan payload 8 byte = (8 * 21296)/69974 ~= 2,423 b/ns ~= 2,268 Gb/s
Opsi tes
Untuk mendapatkan hasil dalam .json, jalankan pengujian dengan argumen --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"
},
….
}
Menjalankan tes latensi
Uji latensi mengukur waktu yang diperlukan klien untuk mulai menginisialisasi transaksi, beralih ke proses server untuk penanganan, dan menerima hasilnya. Pengujian juga mencari perilaku penjadwal buruk yang diketahui dapat berdampak negatif pada latensi transaksi, seperti penjadwal yang tidak mendukung pewarisan prioritas atau menghormati bendera sinkronisasi.
- Tes latensi pengikat ada di
frameworks/native/libs/binder/tests/schd-dbg.cpp
. - Tes latensi hwbinder ada di
system/libhwbinder/vts/performance/Latency.cpp
.
Hasil tes
Hasil (dalam .json) menunjukkan statistik untuk latensi rata-rata/terbaik/terburuk dan jumlah tenggat waktu yang terlewat.
Opsi tes
Tes latensi mengambil opsi berikut:
Memerintah | Keterangan |
---|---|
-i value | Tentukan jumlah iterasi. |
-pair value | Tentukan jumlah pasangan proses. |
-deadline_us 2500 | Tentukan tenggat waktu di kami. |
-v | Dapatkan keluaran verbose (debugging). |
-trace | Menghentikan jejak pada hit tenggat waktu. |
Bagian berikut merinci setiap opsi, menjelaskan penggunaan, dan memberikan contoh hasil.
Menentukan iterasi
Contoh dengan sejumlah besar iterasi dan keluaran verbose dinonaktifkan:
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"
}
Hasil tes ini menunjukkan sebagai berikut:
-
"pair":3
- Membuat satu pasangan klien dan server.
-
"iterations": 5000
- Termasuk 5000 iterasi.
-
"deadline_us":2500
- Batas waktu adalah 2500us (2.5ms); sebagian besar transaksi diharapkan memenuhi nilai ini.
-
"I": 10000
- Satu iterasi pengujian mencakup dua (2) transaksi:
- Satu transaksi dengan prioritas normal (
CFS other
) - Satu transaksi dengan prioritas waktu nyata (
RT-fifo
)
- Satu transaksi dengan prioritas normal (
-
"S": 9352
- 9352 transaksi disinkronkan di CPU yang sama.
-
"R": 0.9352
- Menunjukkan rasio di mana klien dan server disinkronkan bersama dalam CPU yang sama.
-
"other_ms":{ "avg":0.2 , "wst":2.8 , "bst":0.053, "miss":2, "meetR":0.9996}
- Kasus rata-rata (
avg
), terburuk (wst
), dan terbaik (bst
) untuk semua transaksi yang dikeluarkan oleh pemanggil prioritas normal. Dua transaksimiss
dari tenggat waktu, membuat rasio pertemuan (meetR
) 0,9996. -
"fifo_ms": { "avg":0.16, "wst":1.5 , "bst":0.067, "miss":0, "meetR":1}
- Mirip dengan
other_ms
, tetapi untuk transaksi yang dikeluarkan oleh klien dengan prioritasrt_fifo
. Kemungkinan (tetapi tidak wajib)fifo_ms
memiliki hasil yang lebih baik daripadaother_ms
, dengan nilaiavg
danwst
yang lebih rendah danmeetR
yang lebih tinggi (perbedaannya bahkan bisa lebih signifikan dengan beban di latar belakang).
Catatan: Beban latar belakang dapat memengaruhi hasil throughput dan tupel other_ms
dalam uji latensi. Hanya fifo_ms
yang dapat menampilkan hasil serupa selama beban latar belakang memiliki prioritas lebih rendah daripada RT-fifo
.
Menentukan nilai pasangan
Setiap proses klien dipasangkan dengan proses server yang didedikasikan untuk klien, dan setiap pasangan dapat dijadwalkan secara independen ke CPU mana pun. Namun, migrasi CPU tidak boleh terjadi selama transaksi selama flag SYNC adalah honor
.
Pastikan sistem tidak kelebihan beban! Sementara latensi tinggi dalam sistem kelebihan beban diharapkan, hasil pengujian untuk sistem kelebihan beban tidak memberikan informasi yang berguna. Untuk menguji sistem dengan tekanan yang lebih tinggi, gunakan -pair #cpu-1
(atau -pair #cpu
dengan hati-hati). Pengujian menggunakan -pair n
dengan n > #cpu
membebani sistem dan menghasilkan informasi yang tidak berguna.
Menentukan nilai batas waktu
Setelah pengujian skenario pengguna yang ekstensif (menjalankan uji latensi pada produk yang memenuhi syarat), kami menentukan bahwa 2,5 ms adalah tenggat waktu yang harus dipenuhi. Untuk aplikasi baru dengan persyaratan yang lebih tinggi (seperti 1000 foto/detik), nilai batas waktu ini akan berubah.
Menentukan keluaran verbose
Menggunakan opsi -v
menampilkan keluaran verbose. Contoh:
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
- Utas layanan dibuat dengan prioritas
SCHED_OTHER
dan dijalankan diCPU:1
denganpid 8674
. - Transaksi pertama kemudian dimulai oleh
fifo-caller
. Untuk melayani transaksi ini, hwbinder meningkatkan prioritas server (pid: 8674 tid: 8676
) menjadi 99 dan juga menandainya dengan kelas penjadwalan sementara (dicetak sebagai???
). Penjadwal kemudian menempatkan proses server diCPU:0
untuk dijalankan dan menyinkronkannya dengan CPU yang sama dengan kliennya. - Penelepon transaksi kedua memiliki prioritas
SCHED_OTHER
. Server menurunkan versinya sendiri dan melayani penelepon dengan prioritasSCHED_OTHER
.
Menggunakan jejak untuk debugging
Anda dapat menentukan opsi -trace
untuk men-debug masalah latensi. Saat digunakan, uji latensi menghentikan perekaman tracelog pada saat latensi buruk terdeteksi. Contoh:
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
Komponen berikut dapat memengaruhi latensi:
- mode pembuatan Android . Mode Eng biasanya lebih lambat dari mode userdebug.
- Kerangka . Bagaimana layanan kerangka kerja menggunakan
ioctl
untuk mengonfigurasi ke pengikat? - Sopir pengikat . Apakah pengemudi mendukung penguncian berbutir halus? Apakah itu berisi semua tambalan pembalik kinerja?
- Versi kernel . Semakin baik kemampuan waktu nyata yang dimiliki kernel, semakin baik hasilnya.
- Konfigurasi kernel . Apakah konfigurasi kernel berisi konfigurasi
DEBUG
sepertiDEBUG_PREEMPT
danDEBUG_SPIN_LOCK
? - Penjadwal kernel . Apakah kernel memiliki penjadwal Energy-Aware (EAS) atau Heterogeneous Multi-Processing (HMP)? Apakah driver kernel ( driver
cpu-freq
, drivercpu-idle
,cpu-hotplug
, dll.) memengaruhi penjadwal?