Mengevaluasi performa

Gunakan Simpleperf untuk mengevaluasi performa perangkat. Simpleperf adalah alat pembuatan profil native untuk aplikasi dan proses native di Android. Gunakan CPU Profiler untuk memeriksa penggunaan CPU aplikasi dan aktivitas thread secara real time.

Ada dua indikator performa yang terlihat oleh pengguna:

  • Performa yang dapat diprediksi dan dirasakan. Apakah antarmuka pengguna (UI) menghilangkan frame atau secara konsisten merender pada 60 FPS? Apakah audio diputar tanpa artefak atau suara letupan? Berapa lama penundaan antara pengguna menyentuh layar dan efek yang ditampilkan di layar?
  • Durasi waktu yang diperlukan untuk operasi yang lebih lama (seperti membuka aplikasi).

Yang pertama lebih terlihat daripada yang kedua. Pengguna biasanya melihat jank, tetapi mereka tidak dapat membedakan waktu startup aplikasi 500 md versus 600 md kecuali jika mereka melihat dua perangkat secara berdampingan. Latensi sentuh langsung terlihat dan berkontribusi signifikan terhadap persepsi perangkat.

Oleh karena itu, di perangkat yang cepat, pipeline UI adalah hal terpenting dalam sistem selain yang diperlukan untuk menjaga pipeline UI tetap berfungsi. Artinya, pipeline UI harus didahulukan daripada pekerjaan lain yang tidak diperlukan untuk UI yang lancar. Untuk mempertahankan UI yang lancar, sinkronisasi latar belakang, pengiriman notifikasi, dan pekerjaan serupa harus ditunda jika pekerjaan UI dapat dijalankan. Performa operasi yang lebih lama (runtime HDR+, startup aplikasi, dll.) dapat dikorbankan untuk mempertahankan UI yang lancar.

Kapasitas versus jitter

Saat mempertimbangkan performa perangkat, kapasitas dan jitter adalah dua metrik yang bermakna.

Kapasitas

Kapasitas adalah jumlah total beberapa resource yang dimiliki perangkat selama jangka waktu tertentu. Hal ini dapat berupa resource CPU, resource GPU, resource I/O, resource jaringan, bandwidth memori, atau metrik serupa. Saat memeriksa performa seluruh sistem, sebaiknya abstrakkan komponen individual dan asumsikan satu metrik yang menentukan performa (terutama saat menyesuaikan perangkat baru karena workload yang berjalan di perangkat tersebut kemungkinan akan diperbaiki).

Kapasitas sistem bervariasi berdasarkan resource komputasi yang online. Mengubah frekuensi CPU/GPU adalah cara utama untuk mengubah kapasitas, tetapi ada cara lain seperti mengubah jumlah core CPU yang online. Oleh karena itu, kapasitas sistem sesuai dengan konsumsi daya; mengubah kapasitas selalu menghasilkan perubahan yang serupa dalam konsumsi daya.

Kapasitas yang diperlukan pada waktu tertentu sebagian besar ditentukan oleh aplikasi yang berjalan. Akibatnya, platform hanya dapat melakukan sedikit penyesuaian kapasitas yang diperlukan untuk workload tertentu, dan cara untuk melakukannya terbatas pada peningkatan runtime (framework Android, ART, Bionic, compiler/driver GPU, kernel).

Jitter

Meskipun kapasitas yang diperlukan untuk workload mudah dilihat, jitter adalah konsep yang lebih tidak jelas. Untuk pengantar yang baik tentang jitter sebagai penghambat sistem yang cepat, sebaiknya baca makalah berjudul The Case of the Missing Supercomputer Performance: Achieving Optimal Performance on the 8,192 processors of ASCI Q. (Makalah ini merupakan penyelidikan tentang alasan superkomputer ASCI Q tidak mencapai performa yang diharapkan dan merupakan pengantar yang baik untuk mengoptimalkan sistem besar.)

Halaman ini menggunakan istilah jitter untuk mendeskripsikan apa yang disebut noise dalam makalah ASCI Q. Jitter adalah perilaku sistem acak yang mencegah pekerjaan yang terlihat berjalan. Jitter sering kali merupakan pekerjaan yang harus dijalankan, tetapi mungkin tidak memiliki persyaratan waktu yang ketat yang menyebabkan pekerjaan tersebut berjalan pada waktu tertentu. Karena bersifat acak, sangat sulit untuk menyangkal keberadaan jitter untuk workload tertentu. Sangat sulit juga untuk membuktikan bahwa sumber jitter yang diketahui adalah penyebab masalah performa tertentu. Alat yang paling umum digunakan untuk mendiagnosis penyebab jitter (seperti pelacakan atau logging) dapat menyebabkan jitter sendiri.

Sumber jitter yang dialami dalam penerapan Android di dunia nyata mencakup:

  • Penundaan penjadwal
  • Pengendali interupsi
  • Kode driver berjalan terlalu lama dengan preemption atau interupsi dinonaktifkan
  • Softirq yang berjalan lama
  • Pertentangan kunci (aplikasi, framework, driver kernel, kunci binder, kunci mmap)
  • Pertentangan deskriptor file saat thread berprioritas rendah memegang kunci pada file, sehingga mencegah thread berprioritas tinggi berjalan
  • Menjalankan kode penting UI di workqueue yang dapat tertunda
  • Transisi tidak ada aktivitas CPU
  • Logging
  • Penundaan I/O
  • Pembuatan proses yang tidak perlu (misalnya, siaran CONNECTIVITY_CHANGE)
  • Page cache thrashing yang disebabkan oleh memori kosong yang tidak cukup

Jumlah waktu yang diperlukan untuk periode jitter tertentu dapat atau tidak dapat berkurang seiring dengan peningkatan kapasitas. Misalnya, jika driver membiarkan interupsi dinonaktifkan saat menunggu pembacaan dari seluruh bus i2c, driver akan memerlukan waktu tetap, terlepas dari apakah CPU berada pada 384 MHz atau 2 GHz. Meningkatkan kapasitas bukanlah solusi yang layak untuk meningkatkan performa saat jitter terlibat. Akibatnya, prosesor yang lebih cepat biasanya tidak akan meningkatkan performa dalam situasi yang dibatasi jitter.

Terakhir, tidak seperti kapasitas, jitter hampir sepenuhnya berada dalam domain vendor sistem.

Konsumsi memori

Konsumsi memori secara tradisional disalahkan atas performa yang buruk. Meskipun konsumsi itu sendiri bukanlah masalah performa, konsumsi dapat menyebabkan jitter melalui overhead lowmemorykiller, memulai ulang layanan, dan page cache thrashing. Mengurangi konsumsi memori dapat menghindari penyebab langsung performa yang buruk, tetapi mungkin ada peningkatan bertarget lainnya yang juga menghindari penyebab tersebut (misalnya, menyematkan framework untuk mencegahnya di-page out saat akan di-page in segera setelahnya).

Menganalisis performa perangkat awal

Memulai dari sistem yang berfungsi tetapi berperforma buruk dan mencoba memperbaiki perilaku sistem dengan melihat kasus individual performa buruk yang terlihat oleh pengguna bukanlah strategi yang baik. Karena performa yang buruk biasanya tidak mudah direproduksi (yaitu, jitter) atau masalah aplikasi, terlalu banyak variabel dalam sistem lengkap yang mencegah strategi ini menjadi efektif. Akibatnya, sangat mudah untuk salah mengidentifikasi penyebab dan melakukan peningkatan kecil sambil melewatkan peluang sistemik untuk memperbaiki performa di seluruh sistem.

Sebagai gantinya, gunakan pendekatan umum berikut saat menyiapkan perangkat baru:

  1. Siapkan sistem untuk melakukan booting ke UI dengan semua driver berjalan dan beberapa setelan governor frekuensi dasar (jika Anda mengubah setelan governor frekuensi, ulangi semua langkah di bawah).
  2. Pastikan kernel mendukung titik pelacakan sched_blocked_reason serta titik pelacakan lainnya dalam pipeline tampilan yang menunjukkan kapan frame dikirimkan ke layar.
  3. Lakukan pelacakan panjang seluruh pipeline UI (dari menerima input melalui IRQ hingga scanout akhir) saat menjalankan workload yang ringan dan konsisten (misalnya, UiBench atau pengujian bola di TouchLatency).
  4. Perbaiki frame drop yang terdeteksi dalam workload yang ringan dan konsisten.
  5. Ulangi langkah 3-4 hingga Anda dapat menjalankan tanpa frame drop selama 20+ detik dalam satu waktu.
  6. Lanjutkan ke sumber jank lain yang terlihat oleh pengguna.

Hal sederhana lainnya yang dapat Anda lakukan sejak awal dalam penyiapan perangkat mencakup:

  • Pastikan kernel Anda memiliki patch titik pelacakan sched_blocked_reason. Titik pelacakan ini diaktifkan dengan kategori pelacakan sched di systrace dan menyediakan fungsi yang bertanggung jawab untuk tidur saat thread tersebut memasuki mode tidur yang tidak dapat diinterupsi. Hal ini sangat penting untuk analisis performa karena mode tidur yang tidak dapat diinterupsi adalah indikator jitter yang sangat umum.
  • Pastikan Anda memiliki pelacakan yang cukup untuk pipeline GPU dan tampilan. Di SOC Qualcomm terbaru, titik pelacakan diaktifkan menggunakan:
  • adb shell "echo 1 > /d/tracing/events/kgsl/enable"
    adb shell "echo 1 > /d/tracing/events/mdss/enable"
    

    Peristiwa ini tetap diaktifkan saat Anda menjalankan systrace sehingga Anda dapat melihat informasi tambahan dalam pelacakan tentang pipeline tampilan (MDSS) di bagian mdss_fb0. Di SOC Qualcomm, Anda tidak akan melihat informasi tambahan tentang GPU dalam tampilan systrace standar, tetapi hasilnya ada dalam pelacakan itu sendiri (untuk mengetahui detailnya, lihat Memahami systrace).

    Yang Anda inginkan dari pelacakan tampilan semacam ini adalah satu peristiwa yang secara langsung menunjukkan bahwa frame telah dikirimkan ke layar. Dari sana, Anda dapat menentukan apakah Anda telah berhasil mencapai waktu render frame; jika peristiwa Xn terjadi kurang dari 16,7 md setelah peristiwa Xn-1 (dengan asumsi layar 60 Hz), berarti Anda tidak mengalami jank. Jika SOC Anda tidak memberikan sinyal tersebut, hubungi vendor Anda untuk mendapatkannya. Proses debug jitter sangat sulit dilakukan tanpa sinyal pasti penyelesaian frame.

Menggunakan benchmark sintetis

Benchmark sintetis berguna untuk memastikan fungsi dasar perangkat ada. Namun, memperlakukan benchmark sebagai proxy untuk performa perangkat yang dirasakan tidak berguna.

Berdasarkan pengalaman dengan SOC, perbedaan performa benchmark sintetis antara SOC tidak berkorelasi dengan perbedaan yang serupa dalam performa UI yang terlihat (jumlah frame yang dihilangkan, waktu frame persentil ke-99, dll.). Benchmark sintetis adalah benchmark khusus kapasitas; jitter hanya memengaruhi performa terukur benchmark ini dengan mencuri waktu dari operasi massal benchmark. Akibatnya, skor benchmark sintetis sebagian besar tidak relevan sebagai metrik performa yang dirasakan pengguna.

Pertimbangkan dua SOC yang menjalankan Benchmark X yang merender 1.000 frame UI dan melaporkan total waktu rendering (skor yang lebih rendah lebih baik).

  • SOC 1 merender setiap frame Benchmark X dalam 10 md dan mendapat skor 10.000.
  • SOC 2 merender 99% frame dalam 1 md,tetapi 1% frame dalam 100 md dan mendapat skor 19.900, skor yang jauh lebih baik.

Jika benchmark menunjukkan performa UI yang sebenarnya, SOC 2 tidak akan dapat digunakan. Dengan asumsi kecepatan refresh 60 Hz, SOC 2 akan memiliki frame janky setiap 1,5 detik operasi. Sementara itu, SOC 1 (SOC yang lebih lambat menurut Benchmark X) akan sangat lancar.

Menggunakan laporan bug

Laporan bug terkadang berguna untuk analisis performa, tetapi karena sangat berat, laporan bug jarang berguna untuk melakukan debug masalah jank sporadis. Laporan bug dapat memberikan beberapa petunjuk tentang aktivitas sistem pada waktu tertentu, terutama jika jank terjadi di sekitar transisi aplikasi (yang dicatat dalam laporan bug). Laporan bug juga dapat menunjukkan kapan ada sesuatu yang salah dengan sistem secara lebih luas yang dapat mengurangi kapasitas efektifnya (seperti thermal throttling atau fragmentasi memori).

Menggunakan TouchLatency

Beberapa contoh perilaku buruk berasal dari TouchLatency, yang merupakan workload berkala pilihan yang digunakan untuk Pixel dan Pixel XL. TouchLatency tersedia di frameworks/base/tests/TouchLatency dan memiliki dua mode: latensi sentuh dan bola memantul (untuk beralih mode, klik tombol di sudut kanan atas).

Pengujian bola memantul sesederhana yang terlihat: Bola memantul di sekitar layar selamanya, terlepas dari input pengguna. Pengujian ini biasanya juga merupakan pengujian yang paling sulit untuk dijalankan dengan sempurna, tetapi semakin dekat dengan pengujian tanpa frame drop, semakin baik perangkat Anda. Pengujian bola memantul sulit dilakukan karena merupakan workload sepele tetapi sangat konsisten yang berjalan pada clock yang sangat rendah (hal ini mengasumsikan perangkat memiliki governor frekuensi; jika perangkat menjalankan clock tetap, turunkan clock CPU/GPU ke mendekati minimum saat menjalankan pengujian bola memantul untuk pertama kalinya). Saat sistem berhenti dan clock turun mendekati tidak ada aktivitas, waktu CPU/GPU yang diperlukan per frame akan meningkat. Anda dapat melihat bola dan melihat jank, serta melihat frame yang terlewat di systrace.

Karena workload sangat konsisten, Anda dapat mengidentifikasi sebagian besar sumber jitter jauh lebih mudah daripada di sebagian besar workload yang terlihat oleh pengguna dengan melacak apa yang sebenarnya berjalan di sistem selama setiap frame yang terlewat, bukan pipeline UI. Clock yang lebih rendah memperkuat efek jitter dengan membuat kemungkinan jitter menyebabkan frame drop menjadi lebih besar. Akibatnya, semakin dekat TouchLatency dengan 60 FPS, semakin kecil kemungkinan Anda mengalami perilaku sistem yang buruk yang menyebabkan jank sporadis dan sulit direproduksi di aplikasi yang lebih besar.

Karena jitter sering kali (tetapi tidak selalu) invarian kecepatan clock, gunakan pengujian yang berjalan pada clock yang sangat rendah untuk mendiagnosis jitter karena alasan berikut:

  • Tidak semua jitter invarian kecepatan clock; banyak sumber hanya menggunakan waktu CPU.
  • Governor harus mendapatkan waktu frame rata-rata mendekati batas waktu dengan menurunkan clock, sehingga waktu yang dihabiskan untuk menjalankan pekerjaan non-UI dapat mendorongnya melewati batas untuk menghilangkan frame.