Pengujian performa antarmuka pengguna (UI) memastikan aplikasi Anda tidak hanya memenuhi persyaratan fungsionalnya, tetapi juga memastikan interaksi pengguna dengan aplikasi Anda berjalan lancar, dengan 60 frame per detik secara konsisten (mengapa 60 fps?), tanpa ada frame yang hilang atau tertunda, atau seperti yang kita sebut jank. Dokumen ini menjelaskan fitur yang tersedia untuk mengukur performa UI dan menyusun pendekatan untuk mengintegrasikan pengukuran performa UI ke dalam praktik pengujian Anda.
Mengukur performa UI
Untuk meningkatkan performa, pertama-tama Anda perlu kemampuan untuk mengukur performa sistem, kemudian mendiagnosis dan mengidentifikasi masalah yang mungkin muncul dari berbagai pipeline Anda.
dumpsys adalah alat Android yang berjalan pada perangkat dan menyimpan informasi menarik mengenai status layanan sistem. Penerusan perintah gfxinfo ke dumpsys akan memberikan output dalam logcat berisi informasi performa yang terkait frame animasi yang terjadi selama fase perekaman.
> adb shell dumpsys gfxinfo <PACKAGE_NAME>
Perintah ini dapat menghasilkan beragam varian data pengaturan waktu frame.
Menggabungkan statistik frame
Dengan Android 6.0 (API level 23) perintah mencetak analisis gabungan data frame ke logcat, yang dikumpulkan selama waktu proses. Contoh:
Stats since: 752958278148ns Total frames rendered: 82189 Janky frames: 35335 (42.99%) 90th percentile: 34ms 95th percentile: 42ms 99th percentile: 69ms Number Missed Vsync: 4706 Number High input latency: 142 Number Slow UI thread: 17270 Number Slow bitmap uploads: 1542 Number Slow draw: 23342
Statistik tingkat tinggi ini menampilkan performa rendering tingkat tinggi aplikasi, serta stabilitasnya di seluruh frame.
Info pengaturan waktu frame yang akurat
Dengan Android 6.0, perintah baru tersedia untuk gfxinfo yang merupakan framestats yang memberikan informasi pengaturan waktu render frame yang sangat detail dari frame terbaru, sehingga Anda dapat melacak dan men-debug masalah dengan lebih akurat.
>adb shell dumpsys gfxinfo <PACKAGE_NAME> framestats
Perintah ini mencetak informasi pengaturan waktu render frame, dengan stempel waktu nanodetik, dari 120 frame terakhir yang dibuat oleh aplikasi. Di bawah ini adalah contoh output mentah dari framestats adb dumpsys gfxinfo {POTAGE_NAME}:
0,27965466202353,27965466202353,27965449758000,27965461202353,27965467153286,27965471442505,27965471925682,27965474025318,27965474588547,27965474860786,27965475078599,27965479796151,27965480589068, 0,27965482993342,27965482993342,27965465835000,27965477993342,27965483807401,27965486875630,27965487288443,27965489520682,27965490184380,27965490568703,27965491408078,27965496119641,27965496619641, 0,27965499784331,27965499784331,27965481404000,27965494784331,27965500785318,27965503736099,27965504201151,27965506776568,27965507298443,27965507515005,27965508405474,27965513495318,27965514061984, 0,27965516575320,27965516575320,27965497155000,27965511575320,27965517697349,27965521276151,27965521734797,27965524350474,27965524884536,27965525160578,27965526020891,27965531371203,27965532114484,
Setiap baris output menyatakan frame yang dihasilkan oleh aplikasi. Setiap baris memiliki jumlah kolom tetap yang menjelaskan waktu yang dihabiskan di setiap tahap saluran penghasil frame. Bagian selanjutnya mendeskripsikan format tersebut secara detail, termasuk apa yang diwakili oleh setiap kolom.
Format data framestats
Karena blok data merupakan output dalam format CSV, Anda dapat langsung menempelkannya ke fitur spreadsheet pilihan, atau mengumpulkan serta mengurainya dengan skrip. Tabel berikut menjelaskan format kolom data output. Semua stempel waktu ditampilkan dalam nanodetik.
- FLAG
- Baris berisi ‘0’ untuk kolom FLAG, total waktu frame-nya dapat dihitung dengan mengurangkan kolom INTENDED_VSYNC dari kolom FRAME_COMPLETED.
- Jika tidak berisi nol, baris ini harus diabaikan, karena frame telah ditetapkan sebagai pencilan dari performa normal, ketika tata letak & penggambaran diperkirakan membutuhkan waktu lebih dari 16 md. Berikut beberapa alasan terjadinya:
- Tata letak jendela berubah (misalnya frame pertama aplikasi atau setelah rotasi)
- Ada kemungkinan frame tersebut terlewati sehingga beberapa nilai akan memiliki stempel waktu sampah. Frame dapat dilewatkan, misalnya jika melebihi 60 fps atau jika tidak ada sesuatu di layar yang berakhir secara kotor, ini bukan berarti pertanda adanya masalah dalam aplikasi.
- INTENDED_VSYNC
- Titik awal yang dimaksudkan untuk frame. Jika nilai ini berbeda dengan VSYNC, berarti ada pekerjaan yang terjadi pada UI thread yang mencegahnya merespons sinyal vsync tepat waktu.
- VSYNC
- Nilai waktu yang digunakan di semua pemroses vsync dan penggambaran untuk frame (callback frame Choreographer, animasi, View.getDrawingTime(), dll…)
- Untuk memahami VSYNC dan caranya memengaruhi aplikasi lebih lanjut, lihat video Memahami VSYNC.
- OLDEST_INPUT_EVENT
- Stempel waktu peristiwa input paling lama dalam antrean input, atau Long.MAX_VALUE jika tidak ada peristiwa input untuk frame tersebut.
- Nilai ini utamanya dimaksudkan untuk pekerjaan platform dan memiliki kegunaan terbatas untuk developer aplikasi.
- NEWEST_INPUT_EVENT
- Stempel waktu peristiwa input terbaru dalam antrean input, atau 0 jika tidak ada peristiwa input untuk frame.
- Nilai ini utamanya dimaksudkan untuk pekerjaan platform dan memiliki kegunaan terbatas untuk developer aplikasi.
- Namun, ada kemungkinan untuk mendapatkan gambaran kasar mengenai besarnya latensi yang ditambahkan aplikasi dengan melihat (FRAME_COMPLETED - NEWEST_INPUT_EVENT).
- HANDLE_INPUT_START
- Stempel waktu saat peristiwa input dikirimkan ke aplikasi.
- Dengan melihat waktu antara stempel waktu ini dan ANIMATION_START, Anda dapat mengukur berapa lama aplikasi menangani peristiwa input.
- Jika angkanya tinggi (>2 md), ini menunjukkan aplikasi menghabiskan waktu yang sangat lama untuk memproses peristiwa input, seperti View.onTouchEvent(), yang mungkin menunjukkan pekerjaan ini perlu dioptimalkan, atau dialihkan ke thread lain. Perhatikan bahwa ada beberapa skenario, seperti peristiwa klik yang meluncurkan aktivitas baru atau serupa, yang diharapkan dan wajar jika angka ini besar.
- ANIMATION_START
- Stempel waktu saat animasi ini terdaftar pada Choreographer yang dijalankan.
- Dengan melihat waktu antara stempel waktu ini dan PERFORM_TRANVERSALS_START, Anda dapat menentukan lama waktu yang diperlukan dalam mengevaluasi semua animator (ObjectAnimator, ViewPropertyAnimator, dan Transitions menjadi hal yang umum) yang sedang berjalan.
- Jika angka ini tinggi (>2 md), periksa untuk mengetahui apakah aplikasi Anda telah menulis animator kustom atau kolom apa saja yang dianimasikan ObjectAnimators dan pastikan semuanya sesuai untuk animasi.
- Untuk mempelajari Choreographer lebih lanjut, lihat video Untuk Lebih Baik atau Buruk.
- PERFORM_TRAVERSALS_START
- Jika mengurangkan DRAW_START dari nilai ini, Anda dapat mengetahui berapa lama fase tata letak & mengukur selesai. (perhatikan, selama scroll, atau animasi, Anda akan berharap angka ini mendekati nol.)
- Untuk mempelajari lebih lanjut fase mengukur & tata letak dari pipeline rendering, lihat video Invalidasi, Tata Letak, dan Performa.
- DRAW_START
- Waktu fase menggambar performTraversals dimulai. Inilah titik awal dari perekaman daftar tampilan dari tampilan apa pun yang tidak divalidasi.
- Waktu antara stempel waktu ini dan SYNC_START adalah lama waktu yang diperlukan untuk memanggil View.draw() di semua tampilan yang tidak divalidasi dalam hierarki.
- Untuk informasi model penggambaran selengkapnya, lihat video Akselerasi Hardware atau Invalidasi, Tata Letak, dan Performa.
- SYNC_QUEUED
- Waktu permintaan sinkronisasi dikirim ke RenderThread.
- Ini menandai titik saat pesan yang memulai fase sinkronisasi dikirim ke RenderThread. Jika waktu antara stempel waktu ini dan SYNC_START diketahui substansial (>0,1 md atau lebih), berarti RenderThread sedang sibuk mengerjakan frame lain. Secara internal, ini digunakan untuk membedakan antara frame yang terlalu banyak melakukan pekerjaan dan melebihi batas 16 md dengan frame yang macet karena frame sebelumnya melebihi batas 16 md.
- SYNC_START
- Waktu fase sinkronisasi menggambar dimulai.
- Jika waktu antara stempel waktu ini dan ISSUE_DRAW_COMMANDS_START diketahui substansial (>0,4 md atau lebih), hal ini biasanya menunjukkan bahwa banyak Bitmap baru yang digambar dan harus diupload ke GPU.
- Untuk memahami fase sinkronisasi lebih lanjut, lihat video Membuat Profil Rendering GPU.
- ISSUE_DRAW_COMMANDS_START
- Waktu saat perender hardware mulai mengeluarkan perintah menggambar ke GPU.
- Waktu antara stempel waktu ini dan FRAME_COMPLETED memberikan gambaran kasar mengenai besarnya pekerjaan GPU yang dihasilkan aplikasi. Masalah seperti overdraw yang terlalu banyak atau efek rendering yang tidak efisien ditampilkan di sini.
- SWAP_BUFFERS
- Waktu saat eglSwapBuffers dipanggil, relatif tidak menarik selain pekerjaan platform.
- FRAME_COMPLETED
- Selesai! Waktu total yang dihabiskan untuk mengerjakan frame ini dapat dihitung dengan melakukan FRAME_COMPLETED - INTENDED_VSYNC.
Anda dapat menggunakan data ini dengan berbagai cara. Satu visualisasi yang sederhana tetapi berguna adalah histogram yang menampilkan distribusi waktu frame (FRAME_COMPLETED - INTENDED_VSYNC) dalam bucket latensi yang berbeda, lihat gambar di bawah. Gambar ini memberi tahu kita secara sekilas bahwa sebagian besar frame sangat bagus - jauh di bawah batas 16 md (digambarkan dengan warna merah), tetapi beberapa frame terlihat jauh melebihi batasnya. Kita dapat melihat perubahan dalam histogram ini seiring waktu untuk mengetahui perpindahan besar-besaran atau pencilan baru yang sedang dibuat. Anda juga dapat membuat grafik latensi input, yaitu waktu yang dihabiskan dalam layout, atau metrik menarik serupa lain berdasarkan banyaknya stempel waktu dalam data.

Penimbunan pengaturan waktu render frame sederhana
Jika Profile GPU rendering (atau Rendering HWUI profil) disetel ke In adb shell dumpsys gfxinfo di Opsi Developer, perintah adb shell dumpsys gfxinfo
akan mencetak informasi waktu untuk 120 frame terbaru, yang dibagi menjadi beberapa macam kategori dengan nilai yang dipisahkan tab. Data ini dapat berguna untuk menunjukkan bagian mana dari pipeline penggambaran yang mungkin lambat pada tingkat tinggi.
Serupa dengan framestats di atas, Anda dapat langsung menempelkannya ke fitur spreadsheet pilihan, atau mengumpulkan dan mengurainya dengan skrip. Gambar berikut menampilkan perincian tentang tempat frame yang dihasilkan aplikasi menghabiskan waktunya.

Hasil dari menjalankan gfxinfo, menyalin output, menempelkannya ke dalam aplikasi spreadsheet, dan membuat grafik data sebagai batang bertumpuk.
Setiap batang vertikal mewakili satu frame animasi; ketinggiannya mewakili jumlah milidetik yang dihabiskannya untuk menghitung frame animasi. Setiap segmen berwarna pada batang ini mewakili tahap berbeda dari pipeline rendering, sehingga Anda dapat melihat bagian mana dari aplikasi yang mungkin menimbulkan hambatan. Untuk informasi selengkapnya tentang memahami dan mengoptimalkan pipeline rendering, lihat video Invalidasi, Tata Letak, dan Performa.
Mengontrol jendela pengumpulan statistik
Framestat dan pengaturan waktu frame sederhana mengumpulkan data dalam periode yang sangat singkat - sekitar dua detik waktu rendering. Untuk mengontrol jangka waktu dengan akurat - misalnya, untuk membatasi data ke animasi tertentu - Anda dapat menyetel ulang semua penghitung, dan menyatukan statistik yang terkumpul.
>adb shell dumpsys gfxinfo <PACKAGE_NAME> reset
Ini juga dapat digunakan bersamaan dengan perintah penimbunan itu sendiri untuk mengumpulkan dan menyetel ulang pada ritme yang teratur, yang mengambil jendela frame kurang-dari-dua-detik secara terus menerus.
Mendiagnosis regresi performa
Identifikasi regresi merupakan langkah pertama yang baik untuk melacak masalah, dan mempertahankan kesehatan aplikasi yang tinggi. Akan tetapi, dumpsys hanya mengidentifikasi keberadaan dan keparahan relatif masalahnya. Anda tetap harus mendiagnosis penyebab khusus dari masalah performa, dan menemukan cara yang sesuai untuk memperbaikinya. Untuk itu, sangat direkomendasikan menggunakan fitur systrace.
Referensi lainnya
Untuk mengetahui informasi selengkapnya tentang cara kerja pipeline rendering Android, masalah umum yang dapat Anda temukan di sana, dan cara memperbaikinya, referensi berikut mungkin berguna untuk Anda:
- Pengetahuan Dasar Performa Rendering
- Mengapa 60fps?
- Android, UI, dan GPU
- Invalidasi, Tata Letak, dan Performa
- Ringkasan pelacakan sistem
Mengotomatiskan pengujian performa UI
Satu pendekatan terhadap pengujian Performa UI adalah meminta seorang penguji melakukan serangkaian operasi pengguna pada aplikasi target, dan melihat dengan kasat mata setiap jank, atau penggunaan waktu yang sangat besar melalui pendekatan berbasis fitur untuk mengetahuinya. Namun, pendekatan manual ini penuh risiko - kemampuan manusia memahami perubahan frekuensi frame sangatlah berbeda-beda, dan pendekatan ini juga menyita waktu, melelahkan, serta rawan error.
Pendekatan yang lebih efisien adalah mencatat dan menganalisis metrik performa kunci dari pengujian UI otomatis. Android 6.0 mencakup kemampuan logging baru yang memudahkan untuk menentukan jumlah dan tingkat keparahan jank dalam animasi aplikasi Anda, serta dapat digunakan untuk membuat proses yang lebih terperinci dalam menentukan performa Anda saat ini dan melacak tujuan performa ke depannya.
Referensi lainnya
Untuk mempelajari topik ini lebih lanjut, lihat referensi berikut.
Codelab
- Codelab Pengujian Performa Otomatis menunjukkan kepada Anda cara menulis dan menjalankan pengujian otomatis serta meninjau hasilnya untuk memahami cara meningkatkan performa aplikasi Anda.