Menganalisis dengan Rendering GPU Profil

Alat Rendering GPU Profil menunjukkan waktu relatif yang diperlukan oleh tiap tahap pipeline rendering untuk merender frame sebelumnya. Pengetahuan ini dapat membantu Anda mengidentifikasi bottleneck dalam pipeline sehingga Anda dapat mengoptimalkan untuk meningkatkan performa rendering aplikasi.

Halaman ini menjelaskan secara singkat proses yang terjadi selama tiap tahap pipeline dan membahas masalah yang dapat menyebabkan bottleneck. Sebelum membaca halaman ini, Anda harus mengetahui informasi yang dijelaskan di Kecepatan rendering GPU profil. Selain itu, untuk memahami cara kerja semua tahapan, akan bermanfaat jika Anda mengetahui cara kerja pipeline rendering.

Representasi visual

Alat Rendering GPU Profil menampilkan tahapan dan waktu relatifnya dalam bentuk grafik: yaitu histogram berkode warna. Gambar 1 menunjukkan contoh tampilan tersebut.

Grafik Rendering GPU Profil
Gambar 1. Grafik Rendering GPU Profil

Tiap segmen dari tiap batang vertikal yang ditampilkan di grafik Rendering GPU Profil mewakili satu tahap pipeline dan ditandai menggunakan warna tertentu di grafik batang. Gambar 2 menunjukkan kunci arti dari tiap warna yang ditampilkan.

Legenda Grafik Rendering GPU Profil
Gambar 2. Legenda Grafik Rendering GPU Profil

Setelah memahami arti tiap warna, Anda dapat menargetkan aspek tertentu aplikasi untuk mencoba mengoptimalkan performa renderingnya.

Tahap-tahap dan artinya

Bagian ini menjelaskan proses yang terjadi selama tiap tahap serta penyebab bottleneck yang perlu diwaspadai.

Penanganan input

Tahap penanganan input pipeline mengukur durasi waktu yang dihabiskan oleh aplikasi dalam menangani peristiwa input. Metrik ini menunjukkan durasi waktu yang dihabiskan oleh aplikasi dalam mengeksekusi kode yang dipanggil sebagai hasil dari callback peristiwa input.

Saat segmen ini besar

Nilai tinggi di area ini biasanya akibat terlalu banyak pekerjaan, atau pekerjaan yang terlalu kompleks, yang terjadi di dalam callback peristiwa pengendali input. Karena callback ini selalu terjadi di thread utama, solusi untuk masalah ini berfokus pada pengoptimalan pekerjaan secara langsung atau pengurangan beban pekerjaan ke thread yang berbeda.

Men-scroll LazyColumn atau LazyRow juga dapat muncul di fase ini. Setelah sentuhan pengguna memenuhi syarat sebagai scroll, daftar lambat akan menggunakan peristiwa sentuh untuk menyusun dan menata item secara dinamis. Jika aplikasi Anda melakukan pekerjaan kustom sebagai respons terhadap perubahan posisi scroll, Anda harus melakukan operasi ini secepat mungkin untuk mencegah penurunan frame. Alat pembuatan profil seperti CPU Profiler di Android Studio atau Perfetto dapat membantu Anda melakukan penyelidikan lebih lanjut. Lihat Ringkasan pelacakan sistem untuk mengetahui informasi selengkapnya.

Animasi

Fase animasi menunjukkan durasi waktu yang diperlukan untuk mengevaluasi semua status animasi yang berjalan di frame tersebut. Beberapa Animation API umum di Compose adalah animate*AsState, Transition, dan Animatable. Selain itu, Recomposer berjalan selama fase ini untuk memproses perubahan status snapshot dan memperbarui komposisi. Artinya, overhead rekomposisi sering kali muncul langsung dalam tahap animasi.

Untuk UI Jetpack Compose, sertakan library Compose Runtime Tracing untuk melihat rekaman aktivitas komposisi mendetail bersama dengan peristiwa sistem.

Saat segmen ini besar

Nilai tinggi di area ini biasanya akibat pekerjaan yang dieksekusi karena perubahan status yang didorong oleh animasi. Misalnya, animasi mengayunkan jari, yang men-scroll LazyColumn atau LazyRow, menyebabkan komposisi, pengukuran, dan alokasi item daftar baru yang cepat.

Ukur

Untuk menggambar composable Anda di layar, Android mengeksekusi tiga fase di seluruh node tata letak dalam hierarki UI Anda.

Pertama, sistem mengukur node tata letak. Setiap composable memiliki batasan dan pengubah spesifik yang menjelaskan batas ukuran objek di layar. Beberapa composable dapat memiliki ukuran tetap tertentu; yang lain memiliki ukuran yang disesuaikan dengan batasan yang diteruskan oleh penampung tata letak induk.

Kedua, sistem menempatkan node tata letak. Setelah Compose menghitung ukuran node turunan selama fase pengukuran, Compose dapat melanjutkan ke fase penempatan, yang akan mengukur dan memosisikan node tata letak di layar.

Sistem selalu melakukan tata letak single-pass ini agar efisien. Saat tata letak composable dibatalkan, Compose akan mengukur node tertentu tersebut dan hanya menyebarkan update tata letak ke hierarki induk jika turunan mengubah ukuran atau batasannya.

Saat segmen ini besar

Segmen besar di area ini berarti aplikasi menghabiskan terlalu banyak waktu dalam fase tata letak, yang terdiri dari penentuan posisi dan ukuran node tata letak. Operasi ini mencakup menjalankan pengubah penempatan dan pengukuran untuk composable, yang dapat menunda persiapan frame jika hierarki tata letak terlalu rumit. Dalam kasus ini, penanganan performa melibatkan pembuatan tolok ukur aplikasi Compose dan mengikuti praktik terbaik performa.

Gunakan CPU Profiler di Android Studio atau Perfetto untuk memeriksa proses tata letak dan mengidentifikasi bottleneck. Lihat Ringkasan pelacakan sistem untuk mengetahui informasi selengkapnya.

Gambar

Tahap gambar menerjemahkan operasi rendering, seperti menggambar latar belakang, bentuk, atau teks, ke dalam urutan perintah menggambar native. Sistem mencatat perintah ini ke dalam daftar tampilan untuk eksekusi GPU.

Kolom Gambar merekam durasi waktu yang diperlukan untuk menyelesaikan pencatatan perintah dalam daftar tampilan, untuk semua node tata letak yang perlu diupdate di layar untuk frame ini. Waktu yang diukur juga berlaku untuk logika gambar kustom yang mungkin Anda miliki di dalam pengubah gambar atau composable Canvas.

Saat segmen ini besar

Dalam bahasa sederhana, Anda dapat memahami metrik ini dengan menampilkan durasi yang diperlukan untuk menjalankan semua perintah gambar untuk setiap node tata letak yang tidak divalidasi. Pengukuran ini mencakup waktu yang dihabiskan untuk mengirimkan perintah ini ke node turunan dan drawable vektor. Untuk alasan ini, jika Anda melihat lonjakan batang ini, penyebabnya dapat berupa banyak composable yang tiba-tiba menjadi tidak divalidasi. Pembatalan validasi mengharuskan perintah gambar dieksekusi ulang dan daftar tampilan node tata letak dibuat ulang. Atau, waktu yang lama mungkin akibat beberapa composable atau kanvas kustom yang memiliki beberapa logika yang sangat kompleks dalam penerapan DrawScope.

Selain itu, Compose sering menangani pengukuran internal dan meneruskan tata letaknya dalam apa yang dianggap platform sebagai fase Draw. Akibatnya, batang Draw yang tinggi dapat disebabkan oleh operasi pengukuran/tata letak internal yang mahal atau berlebihan, bukan hanya perintah menggambar. Jika ragu, ambil rekaman aktivitas Perfetto untuk melihat apakah overhead berasal dari rutin menggambar atau pengukuran dan tata letak Compose.

Upload

Metrik upload mewakili waktu yang diperlukan untuk mentransfer objek bitmap dari memori CPU ke memori GPU selama frame saat ini.

Sebagai prosesor yang berbeda, CPU dan GPU memiliki area RAM yang didedikasikan untuk pemrosesan. Saat Anda menggambar bitmap di Android, sistem mentransfer bitmap ke memori GPU sebelum GPU dapat merendernya ke layar. Kemudian, GPU menyimpan cache bitmap agar sistem tidak perlu mentransfer data lagi, kecuali tekstur dikeluarkan dari cache tekstur GPU.

Catatan: Di perangkat Lollipop, tahap ini berwarna ungu.

Saat segmen ini besar

Semua resource untuk frame harus berada dalam memori GPU agar dapat digunakan untuk menggambar frame. Ini berarti bahwa nilai tinggi metrik ini dapat menunjukkan sejumlah besar muatan resource kecil atau sejumlah kecil resource yang sangat besar. Kasus yang umum terjadi adalah saat aplikasi menampilkan satu bitmap yang mendekati ukuran layar. Kasus lainnya adalah saat aplikasi menampilkan sejumlah besar thumbnail.

Untuk mengecilkan batang ini, Anda dapat menerapkan teknik seperti:

  • Memastikan resolusi bitmap tidak lebih besar dari ukuran yang akan ditampilkan. Misalnya, hindari menampilkan gambar 1024x1024 sebagai gambar 48x48.
  • Memanfaatkan library modern seperti Coil untuk mengupload bitmap terlebih dahulu secara asinkron sebelum fase sinkronisasi berikutnya.

Menerbitkan perintah

Segmen perintah masalah mewakili waktu yang diperlukan untuk menerbitkan semua perintah yang diperlukan untuk menggambar daftar tampilan ke layar.

Agar sistem dapat menggambar daftar tampilan ke layar, sistem mengirimkan perintah yang diperlukan ke GPU. Biasanya, sistem melakukan tindakan ini melalui OpenGL ES API.

Proses ini memerlukan waktu karena sistem melakukan transformasi akhir dan penyesuaian nilai untuk tiap perintah sebelum mengirimkan perintah ke GPU. Overhead tambahan kemudian muncul di sisi GPU, yang menghitung perintah akhir. Perintah ini mencakup transformasi akhir dan penyesuaian nilai tambahan.

Saat segmen ini besar

Waktu yang dihabiskan dalam tahap ini adalah ukuran langsung dari kompleksitas dan kuantitas daftar tampilan yang dirender oleh sistem pada frame tertentu. Misalnya, banyaknya operasi gambar, terutama dalam kasus adanya biaya inheren kecil untuk tiap primitive gambar, dapat meng-inflate waktu ini. Contoh:

for (i in 0 until 1000) {
    canvas.drawPoint()
}

jauh lebih mahal untuk diterbitkan daripada:

canvas.drawPoints(thousandPointArray)

Tidak selalu ada korelasi 1:1 antara menerbitkan perintah dan menggambar daftar tampilan dengan sebenarnya. Tidak seperti batang perintah penerbitan, yang mencatat waktu yang diperlukan untuk mengirimkan perintah menggambar ke GPU, metrik gambar mewakili waktu yang diperlukan untuk mencatat perintah yang diterbitkan ke daftar tampilan.

Perbedaan ini muncul karena daftar tampilan disimpan dalam cache oleh sistem setiap kali memungkinkan. Akibatnya, ada situasi saat scroll, transformasi, atau animasi mengharuskan sistem untuk mengirim ulang daftar tampilan, tetapi tidak harus mem-buildnya ulang dengan sebenarnya—mencatat ulang perintah menggambar—dari awal. Akibatnya, Anda dapat melihat batang perintah penerbitan yang tinggi tanpa melihat batang perintah menggambar yang tinggi.

Menukar buffer

Setelah Android selesai mengirimkan daftar tampilannya ke GPU, sistem menerbitkan satu perintah akhir untuk memberi tahu driver grafis bahwa sistem sudah selesai dengan frame saat ini. Di titik ini, driver akhirnya dapat menyajikan gambar yang diupdate ke layar.

Saat segmen ini besar

Penting untuk memahami bahwa GPU mengeksekusi pekerjaan secara paralel dengan CPU. Sistem Android menerbitkan perintah menggambar ke GPU, lalu berpindah ke tugas berikutnya. GPU membaca perintah menggambar tersebut dari antrean dan memprosesnya.

Ketika CPU menerbitkan perintah lebih cepat daripada GPU mengonsumsinya, antrean komunikasi antarprosesor dapat menjadi penuh. Jika ini terjadi, CPU akan memblokir dan menunggu hingga ada ruang dalam antrean untuk menempatkan perintah berikutnya. Status antrean penuh ini sering muncul selama tahap swap buffer, karena di titik tersebut, perintah dari seluruh frame telah dikirim.

Kunci untuk memitigasi masalah ini adalah mengurangi kompleksitas pekerjaan yang terjadi di GPU, dengan cara yang serupa dengan yang Anda lakukan untuk fase menerbitkan perintah.

Lain-lain

Selain waktu yang diperlukan oleh sistem render untuk melakukan pekerjaannya, ada set pekerjaan tambahan yang terjadi di thread utama dan tidak berkaitan dengan rendering. Waktu yang dihabiskan oleh pekerjaan ini dilaporkan sebagai waktu lain-lain. Waktu lain-lain biasanya mewakili pekerjaan yang mungkin terjadi di thread UI antara dua frame rendering berturut-turut.

Saat segmen ini besar

Jika nilai ini tinggi, ada kemungkinan bahwa aplikasi memiliki callback, intent, atau pekerjaan lain yang harus dilakukan di thread lain. Alat seperti CPU Profiler di Android Studio atau Perfetto dapat memberikan visibilitas ke dalam tugas yang sedang berjalan di thread utama. Informasi ini dapat membantu Anda menargetkan penyempurnaan performa. Lihat Ringkasan pelacakan sistem untuk mengetahui informasi selengkapnya.