Dokumen ini membantu Anda mengidentifikasi dan mengatasi masalah performa utama di aplikasi.
Masalah performa utama
Ada banyak masalah yang dapat menyebabkan performa buruk di aplikasi, tetapi berikut adalah beberapa masalah umum yang harus diperhatikan di aplikasi Anda:
- Latensi pengaktifan
Latensi pengaktifan adalah jumlah waktu yang dibutuhkan antara mengetuk ikon aplikasi, notifikasi, atau titik entri lainnya, dengan data pengguna yang ditampilkan di layar.
Targetkan beberapa sasaran pengaktifan berikut di aplikasi Anda:
Cold start berlangsung kurang dari 500 md. Cold start terjadi saat aplikasi yang diluncurkan tidak ada di dalam memori sistem. Proses ini terjadi saat aplikasi diluncurkan pertama kali sejak dimulai ulang atau sejak proses aplikasi dihentikan oleh pengguna atau sistem.
Sebaliknya, warm start terjadi saat aplikasi sudah beroperasi di latar belakang. Cold start memerlukan pekerjaan paling banyak dari sistem, karena harus memuat semuanya dari penyimpanan dan menginisialisasi aplikasi. Cobalah untuk membuat cold start berlangsung dalam 500 md atau kurang.
Latensi P95 dan P99 sangat dekat dengan latensi median. Jika aplikasi memerlukan waktu lama untuk dimulai, pengalaman pengguna aplikasi tersebut dinilai buruk. Komunikasi antar-proses (IPC) dan I/O yang tidak perlu selama jalur penting peluncuran aplikasi dapat mengalami pertentangan kunci dan menyebabkan inkonsistensi.
- Jank scroll
Jank adalah istilah yang menjelaskan gangguan visual yang terjadi saat sistem tidak dapat membuat dan menyediakan frame tepat waktu untuk menggambarnya ke layar pada ritme 60 Hz yang diminta atau yang lebih tinggi. Jank terlihat paling jelas saat men-scroll, ketika alur animasi yang lancar mengalami gangguan. Jank muncul saat gerakan terjeda untuk satu atau beberapa frame, karena aplikasi membutuhkan waktu lebih lama untuk merender konten daripada durasi frame pada sistem.
Aplikasi harus menargetkan kecepatan refresh 90 Hz. Kecepatan rendering konvensional adalah 60 Hz, tetapi banyak perangkat baru beroperasi dalam mode 90 Hz selama interaksi pengguna, seperti men-scroll. Beberapa perangkat mendukung kecepatan yang lebih tinggi hingga 120 Hz.
Untuk melihat kecepatan refresh yang digunakan oleh perangkat pada waktu tertentu, aktifkan overlay menggunakan Opsi Developer > Tampilkan kecepatan refresh di bagian Proses debug.
- Transisi yang tidak lancar
Hal ini terlihat selama interaksi, seperti saat beralih antar-tab atau memuat aktivitas baru. Jenis transisi ini harus dalam bentuk animasi yang halus dan tidak menyertakan penundaan atau kedipan visual.
- Inefisiensi daya
Melakukan pekerjaan akan mengurangi daya baterai, dan melakukan pekerjaan yang tidak perlu akan mengurangi daya tahan baterai.
Alokasi memori, yang berasal dari pembuatan objek baru di dalam kode, dapat menjadi penyebab tugas yang signifikan dalam sistem. Hal ini karena alokasi itu sendiri tidak hanya memerlukan upaya dari Android Runtime (ART), tetapi pengosongan objek ini nantinya (pembersihan sampah memori) juga memerlukan waktu dan upaya. Alokasi dan pengumpulan berlangsung jauh lebih cepat dan lebih efisien, terutama untuk objek sementara. Meskipun menghindari pengalokasian objek setiap kali memungkinkan dianggap sebagai praktik terbaik, sebaiknya lakukan hal yang paling sesuai untuk aplikasi dan arsitektur Anda. Menghemat alokasi dengan risiko kode yang tidak dapat dipertahankan bukanlah praktik terbaik, mengingat kemampuan yang dimiliki ART.
Namun, tindakan ini membutuhkan upaya, jadi perlu diingat bahwa tindakan ini dapat menyebabkan masalah performa jika Anda mengalokasikan banyak objek di loop dalam.
Mengidentifikasi masalah
Kami merekomendasikan alur kerja berikut untuk mengidentifikasi dan memperbaiki masalah performa:
- Identifikasi dan periksa perjalanan penting pengguna berikut:
- Alur peluncuran umum, termasuk dari peluncur dan notifikasi.
- Layar tempat pengguna men-scroll data.
- Transisi antar-layar.
- Alur yang berjalan lama, seperti navigasi atau pemutaran musik.
- Periksa semua yang terjadi selama alur sebelumnya dengan menggunakan alat proses debug
berikut:
- Perfetto: memungkinkan Anda melihat apa yang terjadi di seluruh perangkat dengan data waktu yang akurat.
- Memory Profiler: memungkinkan Anda melihat alokasi memori yang terjadi pada heap.
- Simpleperf: menampilkan flamegraph panggilan fungsi yang paling banyak menggunakan CPU selama jangka waktu tertentu. Saat Anda mengidentifikasi sesuatu yang memerlukan waktu lama di Systrace, tetapi Anda tidak tahu alasannya, Simpleperf dapat memberikan informasi tambahan.
Untuk memahami dan men-debug masalah performa ini, sangat penting untuk melakukan debug setiap pengujian yang dijalankan secara manual. Anda tidak dapat mengganti langkah sebelumnya dengan menganalisis data gabungan. Namun, untuk memahami apa yang sebenarnya dilihat pengguna dan mengidentifikasi saat terjadinya regresi, penting untuk menyiapkan pengumpulan metrik di dalam pengujian otomatis dan di kolom:
- Alur pengaktifan
- Metrik kolom: Waktu startup Konsol Play
- Pengujian lab: menguji peluncuran dengan Macrobenchmark
- Jank
- Metrik kolom
- Tanda vital frame Konsol Play: di Konsol Play, Anda tidak dapat mempersempit metrik ke perjalanan pengguna tertentu. Fungsi ini hanya melaporkan keseluruhan jank yang ada di seluruh aplikasi.
- Pengukuran kustom dengan
FrameMetricsAggregator
: Anda dapat menggunakanFrameMetricsAggregator
untuk merekam metrik jank selama alur kerja tertentu.
- Pengujian lab
- Men-scroll dengan Macrobenchmark.
- Macrobenchmark mengumpulkan waktu render frame dengan menggunakan perintah
dumpsys gfxinfo
yang mengelompokkan perjalanan pengguna. Cara ini digunakan untuk memahami variasi di dalam jank selama perjalanan pengguna tertentu. MetrikRenderTime
, yang menyoroti lamanya waktu yang diperlukan untuk menggambar frame, lebih penting daripada jumlah frame yang mengalami jank untuk mengidentifikasi regresi atau peningkatan.
- Metrik kolom
Masalah verifikasi Link Aplikasi
Link Aplikasi adalah deep link yang didasarkan pada URL situs yang telah diverifikasi sebagai bagian dari situs Anda. Berikut adalah alasan yang dapat menyebabkan verifikasi App Link gagal.
- Cakupan filter intent: hanya tambahkan
autoVerify
ke filter intent untuk URL yang dapat direspons aplikasi Anda. - Pengalihan protokol yang tidak diverifikasi: pengalihan subdomain dan sisi server yang tidak diverifikasi
dianggap sebagai risiko keamanan dan gagal dalam verifikasi. Hal ini menyebabkan semua
link
autoVerify
gagal. Misalnya, mengalihkan link dari HTTP ke HTTPS, seperti example.com ke www.example.com, tanpa memverifikasi link HTTPS dapat menyebabkan verifikasi gagal. Pastikan untuk memverifikasi Link Aplikasi dengan menambahkan filter intent. - Link yang tidak dapat diverifikasi: menambahkan link yang tidak dapat diverifikasi untuk tujuan pengujian dapat menyebabkan sistem tidak memverifikasi Link Aplikasi untuk aplikasi Anda.
- Server tidak andal: pastikan server Anda dapat terhubung ke aplikasi klien.
Menyiapkan aplikasi untuk analisis performa
Penting untuk melakukan penyiapan yang benar guna mendapatkan benchmark yang akurat, dapat diulang, dan dapat ditindaklanjuti dari aplikasi. Uji pada sistem yang sedekat mungkin dengan produksi, sambil meredam sumber derau. Bagian ini menampilkan langkah-langkah khusus APK dan sistem yang dapat Anda terapkan untuk mempersiapkan penyiapan pengujian, beberapa di antaranya mencakup kasus penggunaan khusus.
Tracepoint
Aplikasi dapat menginstrumentasikan kodenya dengan peristiwa rekaman aktivitas kustom.
Saat aktivitas direkam, perekaman aktivitas menimbulkan overhead kecil sekitar 5μs per bagian, jadi jangan dilakukan di setiap metode. Perekaman aktivitas pada bagian tugas yang lebih besar dengan >0,1 md dapat memberikan insight yang signifikan tentang bottleneck.
Pertimbangan APK
Varian debug dapat berguna untuk pemecahan masalah dan melambangkan contoh stack,
tetapi variasi tersebut memiliki dampak yang parah terhadap performa. Perangkat yang menjalankan Android 10 (Level
API 29) dan yang lebih tinggi dapat menggunakan profileable android:shell="true"
dalam manifesnya untuk mengaktifkan pembuatan profil dalam build rilis.
Gunakan konfigurasi penyingkatan kode berkelas produksi. Bergantung pada resource yang digunakan aplikasi Anda, hal ini dapat berdampak besar terhadap performa. Beberapa konfigurasi ProGuard menghapus tracepoint, jadi pertimbangkan untuk menghapus aturan tersebut untuk konfigurasi yang Anda gunakan saat menjalankan pengujian.
Kompilasi
Kompilasi aplikasi Anda di perangkat ke status yang diketahui—umumnya speed
untuk
kemudahan, atau speed-profile
untuk performa produksi yang lebih cocok
(meskipun hal ini memerlukan pemanasan aplikasi dan profil pembuangan, atau
mengompilasi profil dasar pengukuran aplikasi).
speed
dan speed-profile
mengurangi jumlah kode yang berjalan
dan ditafsirkan dari dex, dan akibatnya jumlah kompilasi just-in-time
(JIT) latar belakang yang dapat menyebabkan gangguan yang signifikan. Hanya speed-profile
yang mengurangi dampak pemuatan class runtime dari dex.
Perintah berikut mengompilasi aplikasi menggunakan mode speed
:
adb shell cmd package compile -m speed -f com.example.packagename
Mode kompilasi speed
mengompilasi metode aplikasi sepenuhnya. Mode
speed-profile
mengompilasi metode dan class aplikasi sesuai dengan
profil jalur kode yang digunakan dan dikumpulkan selama penggunaan aplikasi. Terkadang
sulit untuk mengumpulkan profil secara konsisten dan benar, jadi jika Anda memutuskan untuk
menggunakannya, pastikan profil tersebut mengumpulkan sesuatu yang diharapkan. Profil tersebut berada di lokasi berikut:
/data/misc/profiles/ref/[package-name]/primary.prof
Pertimbangan sistem
Untuk pengukuran level rendah dan fidelitas tinggi, kalibrasikan perangkat Anda. Jalankan perbandingan A/B di perangkat dan versi OS yang sama. Mungkin akan ditemukan perbedaan yang signifikan dalam hal performa, bahkan pada jenis perangkat yang sama.
Di perangkat yang telah di-root, pertimbangkan untuk menggunakan skrip lockClocks
untuk
Microbenchmarks. Di antara hal lain, skrip ini melakukan hal berikut:
- Menempatkan CPU pada frekuensi yang tetap.
- Menonaktifkan core kecil dan mengonfigurasi GPU.
- Menonaktifkan throttling termal.
Sebaiknya jangan gunakan skrip lockClocks
untuk pengujian yang berfokus pada pengalaman pengguna
seperti peluncuran aplikasi, pengujian DoU, dan pengujian jank, tetapi penggunaan skrip mungkin penting untuk
mengurangi derau di dalam pengujian Microbenchmark.
Jika memungkinkan, pertimbangkan untuk menggunakan framework pengujian seperti Macrobenchmark, yang dapat mengurangi derau dalam pengukuran dan mencegah ketidakakuratan pengukuran.
Waktu pengaktifan aplikasi lambat: aktivitas trampolin yang tidak perlu
Aktivitas trampolin dapat memperpanjang waktu peluncuran aplikasi dan
penting untuk diketahui jika aplikasi melakukannya. Seperti yang ditunjukkan di contoh rekaman aktivitas
berikut, satu activityStart
langsung diikuti oleh activityStart
lainnya
tanpa frame yang digambar oleh aktivitas pertama.
Hal ini dapat terjadi di titik entri notifikasi maupun titik entri peluncuran aplikasi reguler, dan biasanya Anda dapat mengatasinya dengan memfaktorkan ulang. Misalnya, jika Anda menggunakan aktivitas tersebut untuk melakukan penyiapan sebelum aktivitas lain berjalan, faktorkan kode ini ke dalam komponen atau library yang dapat digunakan kembali.
Alokasi yang tidak diperlukan memicu seringnya GC
Anda mungkin akan melihat pembersihan sampah memori (GC) terjadi lebih sering daripada yang Anda harapkan terjadi di Systrace.
Di contoh berikut, setiap 10 detik selama operasi yang berjalan lama adalah indikator bahwa aplikasi mungkin dialokasikan secara tidak perlu tetapi konsisten dari waktu ke waktu:
Anda mungkin juga menyadari bahwa stack panggilan tertentu membutuhkan sebagian besar alokasi saat menggunakan Memory Profiler. Anda tidak perlu menghilangkan semua alokasi secara agresif, karena hal ini dapat membuat kode lebih sulit dipertahankan. Sebagai gantinya, mulailah dengan mengerjakan hotspot alokasi.
Frame yang mengalami jank
Pipeline grafis relatif rumit, dan mungkin terdapat perbedaan kecil mengenai ketentuan apakah pengguna pada akhirnya akan melihat penurunan frame atau tidak. Di beberapa kasus, platform dapat "menyelamatkan" frame dengan menggunakan buffering. Namun, Anda dapat mengabaikan sebagian besar perbedaan kecil tersebut untuk mengidentifikasi frame yang bermasalah dari perspektif aplikasi Anda.
Jika frame digambar dengan sedikit pekerjaan yang diperlukan dari aplikasi,
tracepoint Choreographer.doFrame()
terjadi pada ritme 16,7 md di perangkat
60 FPS:
Saat memperkecil dan menavigasi rekaman aktivitas, terkadang Anda akan melihat frame memerlukan waktu sedikit lebih lama untuk diselesaikan, tetapi itu tidak masalah karena frame tersebut tidak memerlukan waktu lebih dari 16,7 md:
Jika Anda melihat gangguan pada ritme reguler ini, gangguan itu disebut frame yang mengalami jank, seperti yang ditunjukkan pada gambar 5:
Anda dapat berlatih dalam mengidentifikasinya.
Di beberapa kasus, Anda perlu memperbesar tracepoint untuk mengetahui informasi selengkapnya tentang
tampilan mana yang di-inflate atau apa yang dilakukan RecyclerView
. Di kasus
lain, Anda mungkin harus melakukan pemeriksaan lebih lanjut.
Untuk informasi selengkapnya tentang cara mengidentifikasi frame yang mengalami jank dan mendebug penyebabnya, lihat Rendering lambat.
Kesalahan umum RecyclerView
Membatalkan validasi seluruh data pendukung RecyclerView
secara tidak perlu dapat
menyebabkan waktu rendering frame yang lama dan terjadinya jank. Sebagai gantinya, untuk meminimalkan jumlah
tampilan yang perlu diperbarui, batalkan validasi data yang berubah saja.
Lihat Menyajikan data dinamis untuk mengetahui cara menghindari panggilan notifyDatasetChanged()
yang mahal, yang menyebabkan konten diperbarui, bukan diganti sepenuhnya.
Jika Anda tidak mendukung setiap RecyclerView
bertingkat dengan benar, hal ini dapat menyebabkan
RecyclerView
internal sepenuhnya dibuat ulang setiap saat. Setiap RecyclerView
bagian dalam
yang bertingkat harus memiliki RecycledViewPool
yang ditetapkan untuk membantu memastikan
tampilan dapat didaur ulang di antara setiap RecyclerView
bagian dalam.
Tidak melakukan pengambilan data yang cukup, atau tidak mengambil data secara tepat waktu, dapat membuat aktivitas membuka bagian bawah daftar scroll menjadi terganggu saat pengguna harus menunggu lebih banyak data dari server. Meskipun secara teknis gangguan ini bukan jank, karena tidak ada batas waktu frame yang terlewat, Anda dapat meningkatkan UX secara signifikan dengan mengubah waktu dan kuantitas pengambilan data agar pengguna tidak perlu menunggu data.
Mendebug aplikasi Anda
Berikut adalah berbagai metode untuk men-debug performa aplikasi Anda. Tonton video berikut untuk mengetahui ringkasan pelacakan sistem dan penggunaan profiler Android Studio.
Men-debug startup aplikasi dengan Systrace
Lihat Waktu startup aplikasi untuk ringkasan proses startup aplikasi, dan lihat video berikut untuk ringkasan pelacakan sistem.
Anda dapat membedakan jenis startup pada tahap berikut:
- Cold startup: mulai membuat proses baru tanpa status tersimpan.
- Warm startup: membuat ulang aktivitas saat menggunakan kembali proses, atau membuat ulang proses dengan status tersimpan.
- Hot startup: memulai ulang aktivitas dan dimulai pada inflasi.
Sebaiknya rekam Systrace dengan aplikasi Pelacakan Sistem di perangkat. Untuk Android 10 dan yang lebih tinggi, gunakan Perfetto. Untuk Android 9 dan yang lebih lama, gunakan Systrace. Sebaiknya lihat file rekaman aktivitas dengan penampil rekaman aktivitas Perfetto berbasis web. Untuk informasi selengkapnya, lihat Ringkasan pelacakan sistem.
Beberapa hal yang perlu diperhatikan antara lain:
- Persaingan monitor: persaingan untuk resource yang dilindungi monitor dapat menyebabkan penundaan yang signifikan pada startup aplikasi.
Transaksi binder sinkron: cari transaksi yang tidak perlu di jalur penting aplikasi Anda. Jika transaksi yang diperlukan mahal, pertimbangkan untuk bekerja sama dengan tim platform terkait untuk melakukan peningkatan.
GC serentak: hal ini umum dan memiliki dampak yang relatif rendah, tetapi jika Anda sering mengalaminya, pertimbangkan untuk memeriksanya dengan profiler memori Android Studio.
I/O: memeriksa I/O yang dilakukan selama startup, dan mencari penghentian yang lama.
Aktivitas yang signifikan pada thread lain: aktivitas ini dapat mengganggu UI thread, jadi perhatikan pekerjaan latar belakang selama startup.
Sebaiknya panggil reportFullyDrawn
saat startup selesai dari
sudut pandang aplikasi untuk pelaporan metrik startup aplikasi yang lebih baik. Lihat bagian Waktu
untuk tampilan penuh untuk mengetahui informasi selengkapnya tentang penggunaan reportFullyDrawn
.
Anda dapat mengekstrak waktu mulai yang ditentukan RFD melalui pemroses rekaman aktivitas Perfetto,
dan peristiwa rekaman aktivitas yang terlihat pengguna akan ditampilkan.
Menggunakan Pelacakan Sistem di perangkat
Anda dapat menggunakan aplikasi tingkat sistem yang disebut Perekam Aktivitas Sistem untuk mengambil pelacakan
sistem di perangkat. Aplikasi ini memungkinkan Anda merekam aktivitas dari perangkat tanpa
perlu mencolokkannya atau menghubungkannya ke adb
.
Menggunakan Memory Profiler Android Studio
Anda dapat menggunakan Memory Profiler Android Studio untuk memeriksa tekanan memori yang mungkin disebabkan oleh kebocoran memori atau pola penggunaan yang buruk. Alat ini memberikan tampilan langsung alokasi objek.
Anda dapat memperbaiki masalah memori di aplikasi dengan mengikuti informasi dari penggunaan Memory Profiler untuk melacak alasan dan frekuensi GC terjadi.
Untuk membuat profil memori aplikasi, lakukan langkah-langkah berikut:
Mendeteksi masalah memori.
Rekam sesi pembuatan profil memori dari perjalanan pengguna yang ingin Anda fokuskan. Cari jumlah objek yang meningkat, seperti yang ditunjukkan pada gambar 7, yang pada akhirnya mengarah ke GC, seperti yang ditunjukkan pada gambar 8.
Setelah mengidentifikasi perjalanan pengguna yang menambah tekanan memori, analisis penyebab utama tekanan memori.
Mendiagnosis hot spot tekanan memori.
Pilih rentang pada linimasa untuk memvisualisasikan Alokasi dan Shallow Size, seperti yang ditunjukkan pada gambar 9.
Ada beberapa cara untuk mengurutkan data ini. Berikut adalah beberapa contoh cara setiap tampilan dapat membantu Anda menganalisis masalah.
Atur menurut class: berguna saat Anda ingin menemukan class yang menghasilkan objek yang seharusnya di-cache atau digunakan kembali dari gabungan memori.
Misalnya, jika Anda melihat aplikasi yang membuat 2.000 objek class yang disebut "Vertex" setiap detik, aplikasi tersebut akan meningkatkan jumlah Alokasi sebesar 2.000 setiap detik dan Anda akan melihatnya saat mengurutkan berdasarkan class. Jika Anda ingin menggunakan kembali objek ini untuk menghindari pembuatan sampah, terapkan kumpulan memori.
Arrange by callstack: berguna saat Anda ingin menemukan tempat adanya jalur panas tempat memori dialokasikan, seperti di dalam loop atau di dalam fungsi tertentu yang melakukan banyak pekerjaan alokasi.
Shallow Size: hanya melacak memori objek itu sendiri. Hal ini berguna untuk melacak class sederhana yang sebagian besar hanya terdiri dari nilai primitif.
Retained Size: menunjukkan total memori karena objek dan referensi yang hanya direferensikan oleh objek. Hal ini berguna untuk melacak tekanan memori karena objek kompleks. Untuk mendapatkan nilai ini, ambil dump memori penuh, seperti yang ditunjukkan pada gambar 10, dan Retained Size ditambahkan sebagai kolom, seperti yang ditunjukkan pada gambar 11.
Mengukur dampak pengoptimalan.
GC lebih jelas dan lebih mudah untuk mengukur dampak pengoptimalan memori. Saat pengoptimalan mengurangi tekanan memori, Anda akan melihat lebih sedikit GC.
Untuk mengukur dampak pengoptimalan, di linimasa profiler, ukur waktu di antara GC. Kemudian, Anda dapat melihat bahwa waktu yang diperlukan antar-GC lebih lama.
Dampak akhir dari peningkatan memori adalah sebagai berikut:
- Penonaktifan karena kehabisan memori kemungkinan akan berkurang jika aplikasi tidak terus-menerus mengalami tekanan memori.
- Memiliki lebih sedikit GC akan meningkatkan metrik jank, terutama di P99. Hal ini karena GC menyebabkan pertentangan CPU, yang dapat menyebabkan perenderan tugas yang ditangguhkan saat GC terjadi.
Direkomendasikan untuk Anda
- Catatan: teks link ditampilkan saat JavaScript nonaktif
- Analisis dan pengoptimalan startup aplikasi {:#app-startup-analysis-optimization}
- Periode frozen
- Menulis Macrobenchmark