Studi kasus: bagaimana tim Gmail Wear OS meningkatkan startup aplikasinya sebesar 50%

Startup aplikasi merepresentasikan kesan pertama aplikasi Anda pada pengguna. Dan pengguna tidak suka menunggu, jadi Anda perlu memastikan aplikasi dimulai dengan cepat. Untuk menunjukkan cara tim pengembangan aplikasi di dunia nyata menemukan dan mendiagnosis masalah pada startup aplikasi mereka, berikut yang dilakukan tim Wear OS Gmail.

Tim Wear OS Gmail melakukan upaya pengoptimalan, dengan fokus khusus pada performa startup aplikasi dan rendering runtime, untuk memenuhi kriteria performa aplikasi tim mereka. Namun, meskipun Anda tidak memiliki batas spesifik untuk menargetkan, hampir selalu ada ruang untuk meningkatkan startup aplikasi jika Anda meluangkan waktu untuk menyelidikinya.

Mengambil rekaman aktivitas dan melihat pengaktifan aplikasi

Untuk mulai menganalisis, ambil rekaman aktivitas yang menyertakan startup aplikasi untuk pemeriksaan lebih dekat di Perfetto atau Android Studio. Studi kasus ini menggunakan Perfetto karena menunjukkan apa yang terjadi di sistem perangkat, selain aplikasi Anda. Saat Anda mengupload rekaman aktivitas di Perfetto, studinya akan terlihat seperti ini:

Gambar 1. Tampilan awal rekaman aktivitas di Perfetto.

Karena fokusnya meningkatkan startup aplikasi, temukan baris dengan metrik kustom Startup Aplikasi Android. Sebaiknya sematkan ke bagian atas tampilan dengan mengklik ikon pin yang muncul saat Anda mengarahkan kursor ke baris. Batang, atau slice, yang Anda lihat di baris Android App Startups menunjukkan rentang waktu yang dicakup startup aplikasi, hingga frame aplikasi pertama digambar ke layar, sehingga Anda harus mencari masalah atau bottleneck di sana.

Baris Android App Startups dengan opsi untuk menyematkan ditandai.
Gambar 2. Sematkan metrik kustom Android App Startups ke bagian atas dasbor untuk memudahkan analisis.

Perhatikan bahwa metrik Android App Startups menunjukkan waktu hingga tampilan awal, meskipun Anda menggunakan reportFullyDrawn(). Untuk mengidentifikasi waktu hingga tampilan penuh, telusuri reportFullyDrawn() di kotak penelusuran Perfetto.

Memeriksa thread utama

Pertama-tama, periksa apa yang terjadi di thread utama. Thread utama sangat penting karena biasanya di situlah semua rendering UI terjadi; saat diblokir, tidak ada gambar yang dapat terjadi dan aplikasi Anda akan tampak berhenti. Jadi, Anda ingin memastikan bahwa tidak ada operasi yang berjalan lama yang terjadi di thread utama.

Untuk menemukan thread utama, cari baris dengan nama paket aplikasi Anda, lalu perluas. Dua baris dengan nama yang sama dengan paket (biasanya dua baris pertama dalam bagian) mewakili thread utama. Dari dua baris thread utama, baris pertama mewakili status CPU dan baris kedua mewakili tracepoint. Sematkan dua baris thread utama di bawah metrik Android App Startups.

Android App Startups dan baris thread utama disematkan.
Gambar 3. Sematkan baris thread utama di bawah metrik kustom Android App Startups untuk membantu analisis.

Waktu yang dihabiskan dalam status dapat dijalankan dan pertentangan CPU

Untuk mendapatkan tampilan gabungan aktivitas CPU selama startup aplikasi, tarik kursor ke thread utama untuk merekam rentang waktu startup aplikasi. Panel Thread States yang muncul menunjukkan jumlah total waktu yang dihabiskan di setiap status CPU dalam rentang waktu yang Anda pilih.

Lihat waktu yang dihabiskan dalam status Runnable. Saat thread berada dalam status Runnable, thread tersedia untuk melakukan tugas, tetapi tidak ada tugas yang dijadwalkan. Hal tersebut dapat menunjukkan bahwa perangkat menerima beban berat dan tidak dapat menjadwalkan tugas prioritas tinggi. Aplikasi teratas yang terlihat oleh pengguna memiliki prioritas tertinggi dalam penjadwalan, sehingga thread utama yang tidak ada aktivitas sering menunjukkan bahwa proses intensif dalam aplikasi Anda, seperti rendering animasi, bersaing dengan thread utama untuk mendapatkan waktu CPU.

Thread utama yang ditandai dengan total waktu dalam berbagai status pada panel Status Thread.
Gambar 4. Nilai waktu relatif dalam status Runnable hingga Running untuk mendapatkan gambaran awal seberapa banyak pertentangan CPU yang ada.

Makin tinggi rasio waktu dalam status Runnable terhadap waktu dalam status Running, semakin besar kemungkinan terjadinya pertentangan CPU. Saat memeriksa masalah performa dengan cara ini, fokuskan pada frame yang berjalan paling lama terlebih dahulu dan lakukan pekerjaan terhadap frame yang lebih kecil.

Saat menganalisis waktu yang dihabiskan dalam status Runnable, pertimbangkan hardware perangkat. Karena aplikasi yang digambarkan sedang berjalan di perangkat wearable dengan dua CPU, harapannya adalah lebih banyak waktu yang dihabiskan dalam status Runnable dan lebih banyak pertentangan CPU dengan proses lain dibandingkan jika kita melihat perangkat dengan lebih banyak CPU. Meskipun lebih banyak waktu yang dihabiskan dalam status Runnable daripada yang diharapkan untuk aplikasi ponsel biasa, hal ini mungkin dapat dipahami dalam konteks perangkat wearable.

Waktu yang dihabiskan di OpenDexFilesFromOat*

Sekarang, periksa waktu yang dihabiskan di OpenDexFilesFromOat*; di rekaman aktivitas, peristiwa terjadi bersamaan dengan irisan bindApplication. Slice ini menunjukkan waktu yang dibutuhkan untuk membaca file DEX aplikasi.

Transaksi binder yang diblokir

Selanjutnya, periksa transaksi binder. Transaksi binder mewakili panggilan antara klien dan server: dalam hal ini, aplikasi (klien) memanggil sistem Android (server) dengan binder transaction, dan server merespons dengan binder reply. Pastikan aplikasi tidak melakukan transaksi binder yang tidak perlu selama startup, karena akan meningkatkan risiko pertentangan CPU. Jika bisa, tunda pekerjaan yang melibatkan panggilan binder setelah periode startup aplikasi. Jika Anda harus melakukan transaksi binder, pastikan transaksi tersebut tidak memerlukan waktu yang lebih lama dari kecepatan refresh Vsync perangkat.

Transaksi binder pertama, yang biasanya terjadi pada waktu yang sama dengan irisan ActivityThreadMain, tampaknya cukup panjang dalam kasus ini. Untuk mengetahui lebih lanjut tentang apa yang mungkin terjadi, ikuti langkah-langkah berikut:

  1. Untuk melihat balasan binder terkait dan mencari tahu lebih lanjut cara transaksi binder diprioritaskan, klik bagian transaksi binder yang diinginkan.
  2. Untuk melihat balasan binder, buka panel Current Selection lalu klik balasan binder di bagian Thread berikut. Kolom Thread juga memberi tahu Anda thread tempat balasan binder terjadi jika Anda ingin membukanya secara manual; thread tersebut akan berada dalam proses yang berbeda. Sebuah baris akan muncul yang menghubungkan transaksi binder dan balasan.

    Sebuah baris menghubungkan panggilan binder dan balasan.
    Gambar 5. Identifikasi transaksi binder yang terjadi selama aplikasi dimulai dan nilai apakah Anda dapat menundanya.
  3. Untuk melihat cara server sistem menangani transaksi binder ini, sematkan thread Cpu 0 dan Cpu 1 ke bagian atas layar.

  4. Temukan proses sistem yang menangani balasan binder dengan menemukan irisan yang menyertakan nama thread balasan binder, dalam hal ini "Binder:687_11 [2542]". Klik proses sistem yang relevan untuk mendapatkan informasi selengkapnya tentang transaksi binder.

Lihat proses sistem ini yang terkait dengan transaksi binder kepentingan yang terjadi di CPU 0:

Proses sistem dengan End State 'Runnable (Preempted).
Gambar 6. Proses sistem berada dalam status Runnable (Preempted), yang menunjukkan bahwa proses mengalami penundaan.

Status Akhir menyatakan Runnable (Preempted), yang berarti proses tertunda karena CPU melakukan hal lain. Untuk mencari tahu apa yang di-preempt, luaskan baris Ftrace Events. Di tab Peristiwa Ftrace yang tersedia, scroll dan cari peristiwa yang terkait dengan thread binder minat "Binder:687_11 [2542]". Saat proses sistem di-preempt, dua peristiwa server sistem yang menyertakan argumen "decon" terjadi, yang berarti peristiwa tersebut terkait dengan pengontrol tampilan. Hal ini terdengar masuk akal karena pengontrol tampilan menempatkan bingkai di layar—tugas yang penting! Jika begitu, biarkan peristiwa tersebut apa adanya.

Peristiwa FTrace yang terkait dengan transaksi binder yang diinginkan ditandai.
Gambar 7. Peristiwa FTrace menunjukkan bahwa transaksi binder mengalami penundaan oleh peristiwa pengontrol tampilan.

aktivitas JIT

Untuk menyelidiki aktivitas kompilasi tepat waktu (JIT), luaskan proses yang termasuk dalam aplikasi Anda, temukan dua baris "Jit thread pool", dan sematkan ke bagian atas tampilan. Karena aplikasi ini mendapatkan manfaat dari Profil Dasar Pengukuran selama startup aplikasi, aktivitas JIT akan sangat sedikit terjadi hingga frame pertama digambar, yang ditandai dengan akhir panggilan Choreographer.doFrame pertama. Namun, perhatikan alasan memulai lambat JIT compiling void, yang menunjukkan bahwa aktivitas sistem terjadi selama tracepoint berlabel Application creation menyebabkan banyak aktivitas JIT latar belakang. Untuk mengatasi hal ini, tambahkan peristiwa yang terjadi segera setelah frame pertama digambar ke Profil Dasar Pengukuran dengan memperluas pengumpulan profil ke titik tempat aplikasi siap digunakan. Dalam banyak kasus, Anda dapat melakukannya dengan menambahkan baris ke akhir pengujian Macrobenchmark pengumpulan Profil Dasar Pengukuran yang menunggu widget UI tertentu muncul di layar, yang menunjukkan bahwa layar telah terisi penuh.

Kumpulan thread Jit dengan irisan 'Jit yang mengompilasi void' ditandai.
Gambar 8. Jika Anda melihat banyak aktivitas JIT, luaskan Profil Dasar Pengukuran Anda ke titik tempat aplikasi siap digunakan.

Hasil

Sebagai hasil analisis ini, tim Wear OS Gmail melakukan peningkatan berikut:

  • Karena mereka melihat pertentangan selama startup aplikasi saat melihat aktivitas CPU, mereka mengganti animasi indikator lingkaran berputar yang digunakan untuk menunjukkan bahwa aplikasi dimuat dengan satu gambar statis. Fungsi ini juga memperpanjang layar pembuka untuk menunda status shimmer, status layar kedua yang digunakan untuk menunjukkan bahwa aplikasi sedang dimuat, untuk membebaskan resource CPU. Ini meningkatkan latensi startup aplikasi sebesar 50%.
  • Dari melihat waktu yang dihabiskan dalam OpenDexFilesFromOat* dan aktivitas JIT, mereka memungkinkan penulisan ulang R8 untuk Profil Dasar Pengukuran. Tindakan ini meningkatkan latensi pengaktifan aplikasi sebesar 20%.

Berikut adalah beberapa tips dari tim tentang cara menganalisis performa aplikasi secara efisien:

  • Siapkan proses berkelanjutan yang dapat otomatis mengumpulkan rekaman aktivitas dan hasil. Sebaiknya siapkan pelacakan otomatis untuk aplikasi Anda menggunakan benchmark.
  • Gunakan pengujian A/B untuk perubahan yang menurut Anda akan meningkatkan kualitas, dan tolak jika ternyata tidak. Anda dapat mengukur performa dalam berbagai skenario menggunakan library Macrobenchmark.

Untuk mempelajari lebih lanjut, lihat referensi berikut: