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 dan aktivitas thread aplikasi secara real time.

Ada dua indikator performa yang dapat dilihat pengguna:

  • Performa yang dapat diprediksi dan terlihat. Apakah antarmuka pengguna (UI) kehilangan frame atau merender secara konsisten pada 60 FPS? Apakah audio diputar tanpa artefak atau popping? 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 akan dapat membedakan waktu startup aplikasi 500 milidetik versus 600 milidetik kecuali mereka melihat dua perangkat secara berdampingan. Latensi sentuh langsung terlihat dan berkontribusi secara signifikan pada persepsi perangkat.

Akibatnya, di perangkat yang cepat, pipeline UI adalah hal terpenting dalam sistem selain hal yang diperlukan untuk menjaga fungsi pipeline UI. Hal ini berarti bahwa pipeline UI harus menggantikan 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. Anda dapat mengorbankan performa operasi yang lebih lama (runtime HDR+, startup aplikasi, dll.) 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 beberapa waktu. Resource ini dapat berupa resource CPU, resource GPU, resource I/O, resource jaringan, bandwidth memori, atau metrik serupa. Saat memeriksa performa seluruh sistem, akan berguna untuk memisahkan setiap komponen dan mengasumsikan satu metrik yang menentukan performa (terutama saat menyesuaikan perangkat baru karena beban kerja yang berjalan di perangkat tersebut kemungkinan sudah tetap).

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 secara online. Oleh karena itu, kapasitas sistem sesuai dengan konsumsi daya; perubahan kapasitas selalu menghasilkan perubahan konsumsi daya yang serupa.

Kapasitas yang diperlukan pada waktu tertentu sebagian besar ditentukan oleh aplikasi yang berjalan. Akibatnya, platform tidak dapat berbuat banyak untuk menyesuaikan kapasitas yang diperlukan untuk beban kerja tertentu, dan cara 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 kabur. Untuk pengantar yang baik tentang jitter sebagai hambatan bagi sistem cepat, sebaiknya baca makalah berjudul The Case of the Missing Supercomputer Performance: Achieving Optimal Performance on the 8,192 processors of ASCI Q. (Ini adalah investigasi tentang alasan superkomputer ASCI Q tidak mencapai performa yang diharapkan dan merupakan pengantar yang bagus untuk mengoptimalkan sistem besar.)

Halaman ini menggunakan istilah jitter untuk menjelaskan apa yang disebut dalam makalah ASCI Q sebagai derau. Jitter adalah perilaku sistem acak yang mencegah pekerjaan yang dapat dirasakan berjalan. Tugas ini sering kali harus dijalankan, tetapi mungkin tidak memiliki persyaratan waktu yang ketat yang menyebabkannya 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 implementasi Android di dunia nyata meliputi:

  • 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)
  • Persaingan deskriptor file saat thread prioritas rendah menahan kunci pada file, sehingga mencegah thread prioritas tinggi berjalan
  • Menjalankan kode penting UI di antrean tugas tempat kode tersebut dapat tertunda
  • Transisi CPU tidak ada aktivitas
  • Logging
  • Penundaan I/O
  • Pembuatan proses yang tidak perlu (misalnya, siaran CONNECTIVITY_CHANGE)
  • Page cache thrashing yang disebabkan oleh memori kosong yang tidak mencukupi

Jumlah waktu yang diperlukan untuk periode jitter tertentu dapat menurun atau tidak menurun seiring dengan peningkatan kapasitas. Misalnya, jika driver membiarkan interupt dinonaktifkan saat menunggu pembacaan dari seluruh bus i2c, akan diperlukan waktu tetap, terlepas dari apakah CPU berada pada 384 MHz atau 2 GHz. Meningkatkan kapasitas bukanlah solusi yang layak untuk meningkatkan performa jika jitter terjadi. 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

Penggunaan memori biasanya disalahkan atas performa yang buruk. Meskipun konsumsi itu sendiri bukan masalah performa, hal ini dapat menyebabkan jitter melalui overhead lowmemorykiller, mulai ulang layanan, dan thrashing cache halaman. Mengurangi penggunaan memori dapat menghindari penyebab langsung performa yang buruk, tetapi mungkin ada peningkatan tertarget lainnya yang juga menghindari penyebab tersebut (misalnya, menyematkan framework untuk mencegahnya dikeluarkan dari paging saat akan dimasukkan ke paging segera setelahnya).

Menganalisis performa perangkat awal

Memulai dari sistem yang berfungsi tetapi berperforma buruk dan mencoba memperbaiki perilaku sistem dengan melihat setiap kasus performa buruk yang terlihat oleh pengguna bukan strategi yang baik. Karena performa 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 sekaligus melewatkan peluang sistemis untuk memperbaiki performa di seluruh sistem.

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

  1. Buat sistem melakukan booting ke UI dengan semua driver berjalan dan beberapa setelan pemerintah frekuensi dasar (jika Anda mengubah setelan pengontrol frekuensi, ulangi semua langkah di bawah).
  2. Pastikan kernel mendukung tracepoint sched_blocked_reason serta tracepoint lainnya di pipeline tampilan yang menunjukkan kapan frame dikirim ke layar.
  3. Ambil rekaman aktivitas panjang dari seluruh pipeline UI (dari menerima input melalui IRQ hingga scanout akhir) saat menjalankan beban kerja yang ringan dan konsisten (misalnya, UiBench atau pengujian bola di TouchLatency).
  4. Perbaiki penurunan frame yang terdeteksi dalam beban kerja yang ringan dan konsisten.
  5. Ulangi langkah 3-4 hingga Anda dapat menjalankannya tanpa frame yang hilang selama lebih dari 20 detik sekaligus.
  6. Lanjutkan ke sumber jank lain yang terlihat oleh pengguna.

Hal sederhana lainnya yang dapat Anda lakukan sejak awal dalam pembuatan perangkat meliputi:

  • Pastikan kernel Anda memiliki patch tracepoint sched_blocked_reason. Tracepoint ini diaktifkan dengan kategori trace sched di systrace dan menyediakan fungsi yang bertanggung jawab untuk tidur saat thread tersebut memasuki tidur yang tidak dapat diganggu. Hal ini sangat penting untuk analisis performa karena sleep yang tidak dapat diganggu adalah indikator jitter yang sangat umum.
  • Pastikan Anda memiliki pelacakan yang memadai untuk GPU dan pipeline tampilan. Pada SOC Qualcomm terbaru, tracepoint 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 rekaman aktivitas tentang pipeline tampilan (MDSS) di bagian mdss_fb0. Pada SOC Qualcomm, Anda tidak akan melihat informasi tambahan tentang GPU di tampilan systrace standar, tetapi hasilnya ada dalam rekaman aktivitas 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 dikirim ke layar. Dari sana, Anda dapat menentukan apakah Anda berhasil mencapai waktu render frame; jika peristiwa Xn terjadi kurang dari 16,7 ms setelah peristiwa Xn-1 (dengan asumsi layar 60 Hz), Anda tahu bahwa Anda tidak mengalami jank. Jika SOC Anda tidak memberikan sinyal tersebut, hubungi vendor Anda untuk mendapatkannya. Men-debug jitter sangat sulit 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 serupa dalam performa UI yang terlihat (jumlah frame yang dihapus, waktu frame persentil ke-99, dll.). Benchmark sintetis adalah benchmark khusus kapasitas; jitter memengaruhi performa terukur dari benchmark ini hanya 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 milidetik dan mendapatkan skor 10.000.
  • SOC 2 merender 99% frame dalam 1 md,tetapi 1% frame dalam 100 md dan skornya 19.900, yang merupakan skor yang jauh lebih baik.

Jika tolok ukur menunjukkan performa UI yang sebenarnya, SOC 2 tidak akan dapat digunakan. Dengan asumsi kecepatan refresh 60 Hz, SOC 2 akan memiliki periode jank setiap operasi 1,5 detik. 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 men-debug masalah jank sporadis. Hal ini dapat memberikan beberapa petunjuk tentang apa yang dilakukan sistem pada waktu tertentu, terutama jika jank terjadi di sekitar transisi aplikasi (yang dicatat dalam laporan bug). Laporan bug juga dapat menunjukkan saat ada masalah yang lebih umum pada sistem yang dapat mengurangi kapasitas efektifnya (seperti throttling termal atau fragmentasi memori).

Menggunakan TouchLatency

Beberapa contoh perilaku buruk berasal dari TouchLatency, yang merupakan beban kerja berkala yang lebih disukai dan digunakan untuk Pixel dan Pixel XL. Fitur ini tersedia di frameworks/base/tests/TouchLatency dan memiliki dua mode: latensi sentuhan dan bola memantul (untuk beralih mode, klik tombol di sudut kanan atas).

Pengujian bola memantul sama sederhananya dengan tampilannya: Bola memantul di sekitar layar selamanya, terlepas dari input pengguna. Pengujian ini biasanya juga jauh merupakan pengujian tersulit untuk dijalankan dengan sempurna, tetapi semakin dekat pengujian ini berjalan tanpa frame yang terputus, semakin baik perangkat Anda. Pengujian bola memantul sulit karena merupakan beban kerja yang tidak penting tetapi sangat konsisten yang berjalan pada clock yang sangat rendah (ini mengasumsikan perangkat memiliki pengontrol frekuensi; jika perangkat berjalan dengan clock tetap, turunkan clock CPU/GPU ke hampir minimum saat menjalankan pengujian bola memantul untuk pertama kalinya). Saat sistem tidak aktif dan clock turun mendekati tidak ada aktivitas, waktu CPU/GPU yang diperlukan per frame akan meningkat. Anda dapat melihat bola dan melihat hal-hal yang mengalami jank, dan Anda juga akan dapat melihat frame yang terlewat di systrace.

Karena beban kerja sangat konsisten, Anda dapat mengidentifikasi sebagian besar sumber jitter dengan lebih mudah daripada di sebagian besar beban kerja yang terlihat pengguna dengan melacak apa yang sebenarnya berjalan di sistem selama setiap frame yang terlewat, bukan pipeline UI. Klok yang lebih rendah akan memperkuat efek jitter dengan meningkatkan kemungkinan jitter menyebabkan frame yang terputus. Akibatnya, semakin dekat TouchLatency ke 60 FPS, semakin kecil kemungkinan Anda memiliki perilaku sistem yang buruk yang menyebabkan jank sporadis yang sulit direproduksi di aplikasi yang lebih besar.

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

  • Tidak semua jitter bersifat invarian clockspeed; banyak sumber hanya menghabiskan waktu CPU.
  • Pengontrol harus mendapatkan waktu frame rata-rata mendekati batas waktu dengan melakukan clock down, sehingga waktu yang dihabiskan untuk menjalankan tugas non-UI dapat mendorongnya ke batas untuk menurunkan frame.