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, agar Anda dapat mengetahui apa saja yang perlu dioptimalkan untuk meningkatkan performa rendering aplikasi.

Halaman ini menjelaskan secara singkat proses yang terjadi selama tiap tahap pipeline, dan membahas masalah yang dapat menyebabkan bottleneck di sana. Sebelum membaca halaman ini, Anda harus mengetahui informasi yang dijelaskan di 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.

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.

Gambar 2. Legenda Grafik Rendering GPU Profil

Setelah memahami arti setiap 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 sesuai dengan warna di Gambar 2, 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.

Juga perlu diperhatikan bahwa scroll RecyclerView dapat muncul di fase ini. RecyclerView akan langsung di-scroll saat memproses peristiwa sentuh. Akibatnya, hal itu dapat meng-inflate atau mengisi tampilan item baru. Karena alasan ini, operasi ini harus dibuat secepat mungkin. Alat pembuatan profil sepertiTraceview atau Systrace dapat membantu Anda menginvestigasi lebih lanjut.

Animasi

Fase Animation menunjukkan kepada Anda durasi waktu yang diperlukan untuk mengevaluasi semua animator yang berjalan di frame tersebut. Animator yang paling umum adalah ObjectAnimator, ViewPropertyAnimator, dan Transisi.

Saat segmen ini besar

Nilai tinggi di area ini biasanya akibat pekerjaan yang dieksekusi karena beberapa perubahan properti animasi. Misalnya, animasi mengayunkan jari, yang men-scroll ListView atau RecyclerView, akan menyebabkan inflation dan pengisian tampilan dalam jumlah besar.

Pengukuran/tata letak

Agar dapat menggambar item tampilan di layar, Android mengeksekusi dua operasi spesifik di tata letak dan tampilan dalam hierarki tampilan.

Pertama, sistem mengukur item tampilan. Setiap tampilan dan tata letak memiliki data spesifik yang menjelaskan ukuran objek di layar. Beberapa tampilan dapat memiliki ukuran tertentu, tampilan lainnya memiliki ukuran yang disesuaikan dengan ukuran container tata letak induk.

Kedua, sistem menyusun tata letak item tampilan. Setelah sistem menghitung ukuran tampilan turunan, sistem dapat melanjutkan dengan tata letak, ukuran dan pemosisian tampilan di layar.

Sistem melakukan pengukuran dan tata letak tidak hanya untuk tampilan yang akan digambar, tetapi juga untuk hierarki induk tampilan tersebut, hingga ke tampilan root.

Saat segmen ini besar

Jika aplikasi menghabiskan banyak waktu per frame di area ini, itu biasanya karena banyaknya volume tampilan yang perlu disusun tata letaknya, atau masalah seperti taksasi ganda di bagian yang salah dalam hierarki. Pada kasus mana pun, penanganan performa melibatkan peningkatan performa hierarki tampilan.

Kode yang Anda tambahkan ke onLayout(boolean, int, int, int, int) atau onMeasure(int, int) juga dapat menyebabkan masalah performa. Traceview dan Systrace dapat membantu Anda memeriksa callstack untuk mengidentifikasi masalah yang dapat dialami oleh kode.

Gambar

Tahap gambar menerjemahkan operasi rendering tampilan, seperti menggambar latar belakang atau menggambar teks ke dalam urutan perintah menggambar native. Sistem mencatat perintah tersebut dalam daftar tampilan.

Batang Gambar merekam durasi waktu yang diperlukan untuk menyelesaikan pencatatan perintah dalam daftar tampilan, untuk semua tampilan yang perlu diupdate di layar pada frame ini. Waktu yang diukur berlaku untuk kode yang telah Anda tambahkan ke objek UI di aplikasi. Contoh kode tersebut dapat berupa onDraw(), dispatchDraw(), dan berbagai draw ()methods yang termasuk dalam subclass dari class Drawable.

Saat segmen ini besar

Dalam bahasa sederhana, Anda dapat memahami metrik ini dengan menampilkan durasi yang diperlukan untuk menjalankan semua panggilan ke onDraw() untuk tiap tampilan yang tidak divalidasi. Pengukuran ini menyertakan waktu yang dihabiskan dalam mengirimkan perintah gambar ke turunan dan drawable yang mungkin ada. Untuk alasan ini, jika Anda melihat lonjakan batang ini, penyebabnya dapat berupa sejumlah tampilan yang tiba-tiba menjadi tidak divalidasi Pembatalan validasi mengharuskan untuk membuat ulang daftar tampilan. Dengan kata lain, waktu yang lama mungkin akibat beberapa tampilan kustom yang memiliki beberapa logika yang sangat kompleks dalam metode onDraw().

Sinkronisasi/upload

Metrik Sinkronisasi & 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. Lalu, 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, aplikasi harus menghindari menampilkan gambar 1024x1024 sebagai gambar 48x48.
  • Memanfaatkan prepareToDraw() untuk mengupload bitmap terlebih dahulu secara asinkron sebelum fase sinkronisasi berikutnya.

Menerbitkan perintah

Segmen Menerbitkan Perintah 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 akan mengirimkan perintah yang diperlukan ke GPU. Biasanya, class ini 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:

Kotlin

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

Java

for (int i = 0; i < 1000; i++) {
    canvas.drawPoint()
}

jauh lebih mahal untuk diterbitkan daripada:

Kotlin

canvas.drawPoints(thousandPointArray)

Java

canvas.drawPoints(thousandPointArray);

Tidak selalu ada korelasi 1:1 antara menerbitkan perintah dan menggambar daftar tampilan dengan sebenarnya. Tidak seperti Menerbitkan Perintah, 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 "Menerbitkan perintah” yang tinggi tanpa melihat batang perintah Gambar yang tinggi.

Buffering proses/pertukaran

Setelah Android selesai mengirimkan semua 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 Buffering Pertukaran, 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 Pelacakan metode atau Systrace dapat memberikan visibilitas ke dalam tugas yang sedang berjalan di thread utama. Informasi ini dapat membantu Anda menargetkan peningkatan performa.