Analisis dan pengoptimalan startup aplikasi

Selama startup aplikasi, aplikasi Anda memberikan kesan pertama bagi pengguna. Startup aplikasi harus dimuat dengan cepat dan menampilkan informasi yang diperlukan pengguna untuk menggunakan aplikasi Anda. Jika aplikasi Anda memerlukan waktu terlalu lama untuk dimulai, pengguna mungkin keluar dari aplikasi Anda karena mereka menunggu terlalu lama.

Sebaiknya gunakan library Macrobenchmark untuk mengukur startup. Library ini menyediakan ringkasan dan pelacakan sistem mendetail untuk melihat secara persis apa yang terjadi selama startup.

Pelacakan sistem memberikan informasi yang berguna tentang apa yang terjadi di perangkat, sehingga Anda dapat memahami apa yang dilakukan aplikasi selama startup dan mengidentifikasi area yang potensial untuk dioptimalkan.

Untuk menganalisis startup aplikasi Anda, lakukan langkah-langkah berikut:

Langkah-langkah untuk menganalisis dan mengoptimalkan startup

Selama startup, aplikasi sering kali perlu memuat resource tertentu yang sangat penting bagi pengguna akhir. Resource yang tidak penting dapat menunggu dimuat hingga setelah startup selesai.

Untuk melakukan penyesuaian performa, pertimbangkan hal-hal berikut:

  • Gunakan library Macrobenchmark untuk mengukur waktu yang dibutuhkan oleh setiap operasi, dan temukan blok yang memerlukan waktu lama untuk diselesaikan.

  • Pastikan bahwa hanya operasi yang membutuhkan banyak resource yang sangat penting untuk startup aplikasi. Jika operasi tersebut dapat menunggu hingga aplikasi digambar sepenuhnya, operasi tersebut dapat membantu meminimalkan batasan resource saat startup.

  • Pastikan bahwa operasi ini memang perlu dijalankan saat startup aplikasi. Sering kali, operasi yang tidak diperlukan dapat dipanggil dari kode lama atau library pihak ketiga.

  • Pindahkan operasi yang berjalan lama ke latar belakang, jika memungkinkan. Proses latar belakang masih dapat memengaruhi penggunaan CPU selama proses startup.

Setelah menyelidiki operasi sepenuhnya, Anda dapat menentukan kompromi antara waktu yang diperlukan untuk memuat dan kebutuhan untuk menyertakannya dalam startup aplikasi. Jangan lupa untuk menyertakan potensi regresi atau perubahan yang dapat menyebabkan gangguan saat mengubah alur kerja aplikasi Anda.

Optimalkan dan ukur ulang sampai Anda puas dengan waktu startup aplikasi Anda. Untuk mengetahui informasi selengkapnya, lihat Menggunakan metrik untuk mendeteksi dan mendiagnosis masalah.

Mengukur dan menganalisis waktu yang dihabiskan dalam operasi besar

Saat Anda memiliki rekaman aktivitas startup aplikasi yang lengkap, lihat rekaman aktivitas tersebut dan ukur waktu yang dibutuhkan untuk operasi besar seperti bindApplication atau activityStart. Sebaiknya gunakan Perfetto atau Profiler Android Studio untuk menganalisis rekaman aktivitas ini.

Lihat keseluruhan waktu yang dihabiskan selama memulai aplikasi untuk mengidentifikasi operasi apa pun yang melakukan hal berikut:

  • Menggunakan jangka waktu yang besar dan dapat dioptimalkan. Setiap milidetik sangat berarti untuk performa. Misalnya, cari waktu menggambar Choreographer, waktu inflate tata letak, waktu pemuatan library, transaksi Binder, atau waktu pemuatan resource. Untuk memulai, lihat semua operasi yang memerlukan waktu lebih dari 20 milidetik.
  • Memblokir thread utama. Untuk mengetahui informasi selengkapnya, lihat Menavigasi laporan Systrace.
  • Tidak perlu dijalankan selama startup.
  • Dapat menunggu hingga setelah frame pertama digambar.

Selidiki setiap rekaman aktivitas ini untuk menemukan selisih performa.

Mengidentifikasi operasi yang mahal di thread utama

Praktik terbaiknya adalah menjauhkan operasi yang mahal seperti I/O file dan akses jaringan dari thread utama. Hal ini juga penting selama startup aplikasi, karena operasi yang mahal di thread utama dapat membuat aplikasi tidak responsif dan menunda operasi penting lainnya. StrictMode.ThreadPolicy dapat membantu mengidentifikasi kasus ketika operasi yang mahal terjadi di thread utama. Sebaiknya aktifkan StrictMode di build debug untuk mengidentifikasi masalah secepat mungkin, seperti yang ditunjukkan dalam contoh berikut:

Kotlin

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()

        ...
        if (BuildConfig.DEBUG)
            StrictMode.setThreadPolicy(
                StrictMode.ThreadPolicy.Builder()
                    .detectAll()
                    .penaltyDeath()
                    .build()
            )
        ...
    }
}

Java

public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        ...
        if(BuildConfig.DEBUG) {
            StrictMode.setThreadPolicy(
                    new StrictMode.ThreadPolicy.Builder()
                            .detectAll()
                            .penaltyDeath()
                            .build()
            );
        }
        ...
    }
}

Penggunaan StrictMode.ThreadPolicy akan mengaktifkan kebijakan thread di semua build debug dan membuat aplikasi error setiap kali pelanggaran kebijakan thread terdeteksi, yang menyulitkan pelanggaran kebijakan thread.

TTID dan TTFD

Untuk melihat waktu yang diperlukan aplikasi untuk menghasilkan frame pertamanya, ukur waktu hingga tampilan awal (TTID). Namun, metrik ini tidak selalu mencerminkan waktu hingga pengguna dapat mulai berinteraksi dengan aplikasi Anda. Metrik waktu hingga tampilan penuh (TTFD) lebih berguna dalam mengukur dan mengoptimalkan jalur kode yang diperlukan agar memiliki status aplikasi yang sepenuhnya dapat digunakan.

Untuk mengetahui strategi pelaporan ketika UI aplikasi telah digambar sepenuhnya, lihat Meningkatkan akurasi waktu startup.

Optimalkan TTID dan TTFD, karena keduanya penting di areanya sendiri. TTID yang rendah membantu pengguna melihat bahwa aplikasi benar-benar diluncurkan. Mempertahankan TTFD agar tetap singkat sangat penting untuk membantu pengguna dapat mulai berinteraksi dengan cepat dengan aplikasi.

Menganalisis status thread secara keseluruhan

Pilih waktu startup aplikasi dan lihat bagian thread secara keseluruhan. Thread utama harus selalu responsif.

Alat seperti Android Studio Profiler dan Perfetto memberikan ringkasan mendetail tentang thread utama dan jumlah waktu yang dihabiskan di setiap tahap. Untuk mengetahui informasi selengkapnya tentang memvisualisasikan rekaman aktivitas perfetto, lihat dokumentasi UI Perfetto.

Mengidentifikasi bagian utama status mode tidur thread utama

Jika mode tidur memakan waktu yang lama, kemungkinan hal tersebut terjadi karena thread utama aplikasi menunggu pekerjaan selesai. Jika Anda memiliki aplikasi multi-thread, identifikasi thread yang ditunggu oleh thread utama, dan pertimbangkan untuk mengoptimalkan operasi tersebut. Hal ini juga berguna untuk memastikan tidak ada pertentangan kunci yang tidak perlu yang menyebabkan penundaan di jalur penting Anda.

Mengurangi pemblokiran thread utama dan mode tidur tanpa gangguan

Cari setiap instance thread utama yang mengalami status diblokir. Perfetto dan Profiler Android Studio menunjukkan hal ini dengan indikator oranye pada linimasa status thread. Identifikasi operasi tersebut, pelajari apakah hal tersebut dapat terjadi atau dapat dihindari, dan optimalkan jika perlu.

Mode tidur terkait IO yang dapat diganggu dapat menjadi peluang peningkatan yang sangat bagus. Proses lain yang melakukan IO, meskipun tidak terkait aplikasi, dapat bersaing dengan IO yang dilakukan aplikasi teratas.

Meningkatkan waktu startup

Setelah Anda mengidentifikasi peluang pengoptimalan, pelajari kemungkinan solusi untuk membantu meningkatkan waktu startup:

  • Muat konten dengan lambat dan asinkron untuk mempercepat TTID.
  • Minimalkan fungsi panggilan yang melakukan panggilan binder. Jika tidak dapat dihindari, pastikan Anda mengoptimalkan panggilan tersebut dengan meng-cache nilai, bukan mengulangi panggilan atau memindahkan pekerjaan yang tidak memblokir ke thread latar belakang.
  • Agar startup aplikasi terlihat lebih cepat, Anda dapat menampilkan sesuatu yang memerlukan rendering minimal kepada pengguna secepat mungkin, hingga seluruh layar selesai dimuat.
  • Buat dan tambahkan profil startup ke aplikasi Anda.
  • Gunakan library Startup Aplikasi Jetpack untuk menyederhanakan inisialisasi komponen selama startup aplikasi.

Menganalisis performa UI

Startup aplikasi mencakup layar pembuka dan waktu pemuatan halaman beranda. Untuk mengoptimalkan startup aplikasi, periksa rekaman aktivitas untuk memahami waktu yang diperlukan untuk menggambar UI Anda.

Membatasi pekerjaan saat inisialisasi

Frame tertentu mungkin memerlukan waktu pemuatan yang lebih lama daripada yang lain. Hal ini dianggap sebagai gambar yang memakan banyak resource aplikasi.

Untuk mengoptimalkan inisialisasi, lakukan langkah berikut:

  • Prioritaskan penerusan tata letak yang lambat dan pilih hal ini untuk peningkatan.
  • Selidiki setiap peringatan dari Perfetto dan peringatan dari Systrace dengan menambahkan peristiwa rekaman aktivitas kustom untuk mengurangi penundaan dan gambar yang memakan banyak resource.

Mengukur data frame

Ada beberapa cara untuk mengukur data frame. Lima metode pengumpulan utama adalah:

  • Pengumpulan lokal menggunakan dumpsys gfxinfo: Tidak semua frame yang diamati dalam data dumpsys bertanggung jawab atas rendering aplikasi yang lambat atau memiliki dampak apa pun kepada pengguna akhir. Namun, ini adalah ukuran yang bagus untuk dilihat di berbagai siklus rilis guna memahami tren performa secara umum. Untuk mempelajari lebih lanjut cara menggunakan gfxinfo dan framestats untuk mengintegrasikan pengukuran performa UI ke dalam praktik pengujian Anda, lihat Dasar-dasar pengujian aplikasi Android.
  • Pengumpulan kolom menggunakan JankStats: Kumpulkan waktu render frame dari bagian tertentu aplikasi Anda dengan library JankStats, serta catat dan analisis data.
  • Dalam pengujian menggunakan Macrobenchmark (Perfetto di balik layar)
  • Perfetto FrameTimelIne: Di Android 12 (API level 31), Anda dapat mengumpulkan Metrik linimasa frame dari rekaman aktivitas Perfetto yang menyebabkan penurunan frame. Ini dapat menjadi langkah pertama untuk mendiagnosis alasan penghapusan frame.
  • Profiler Android Studio untuk deteksi jank

Memeriksa waktu pemuatan aktivitas utama

Aktivitas utama aplikasi mungkin berisi informasi dalam jumlah besar yang dimuat dari beberapa sumber. Periksa tata letak Activity beranda dan secara khusus lihat metode Choreographer.onDraw aktivitas beranda.

  • Gunakan reportFullyDrawn untuk melaporkan ke sistem bahwa aplikasi Anda sekarang sepenuhnya digambar untuk tujuan pengoptimalan.
  • Ukur aktivitas dan peluncuran aplikasi menggunakan StartupTimingMetric dengan library Macrobenchmark.
  • Perhatikan penghapusan frame.
  • Identifikasi tata letak yang memerlukan waktu lama untuk dirender atau diukur.
  • Identifikasi aset yang memerlukan waktu lama untuk dimuat.
  • Identifikasi tata letak yang tidak perlu yang di-inflate selama startup.

Pertimbangkan kemungkinan solusi ini untuk mengoptimalkan waktu pemuatan aktivitas utama:

  • Buat tata letak sedasar mungkin. Untuk mengetahui informasi selengkapnya, lihat Mengoptimalkan hierarki tata letak.
  • Tambahkan tracepoint kustom untuk memberikan informasi selengkapnya tentang penghapusan frame dan tata letak yang kompleks.
  • Minimalkan jumlah dan ukuran resource bitmap yang dimuat selama startup.
  • Gunakan ViewStub jika tata letak tidak langsung berstatus VISIBLE. ViewStub adalah Tampilan tidak terlihat berukuran nol yang dapat digunakan untuk memperluas resource tata letak sesuai keinginan selama runtime. Untuk mengetahui informasi selengkapnya, lihat ViewStub.

    Jika menggunakan Jetpack Compose, Anda bisa mendapatkan perilaku yang serupa dengan ViewStub menggunakan status untuk menunda pemuatan beberapa komponen:

    var shouldLoad by remember {mutableStateOf(false)}
    
    if (shouldLoad) {
     MyComposable()
    }
    

    Muat composeable di dalam blok kondisional dengan mengubah shouldLoad:

    LaunchedEffect(Unit) {
     shouldLoad = true
    }
    

    Tindakan ini akan memicu rekomposisi yang menyertakan kode di dalam blok kondisional dalam cuplikan pertama.