Membuat profil build

Pada project yang lebih besar, atau yang mengimplementasikan banyak logika build kustom, Anda mungkin harus melihat proses build secara lebih detail untuk menemukan bottleneck. Anda dapat melakukannya dengan membuat profil durasi yang diperlukan Gradle untuk menjalankan setiap fase siklus proses build dan setiap tugas build. Misalnya, jika profil build Anda menunjukkan bahwa Gradle menghabiskan terlalu banyak waktu untuk mengonfigurasi project, hal ini mungkin menunjukkan bahwa Anda perlu memindahkan logika build kustom dari fase konfigurasi. Selain itu, jika tugas mergeDevDebugResources menghabiskan banyak waktu build, hal ini mungkin menunjukkan bahwa Anda perlu mengonversi gambar ke WebP atau menonaktifkan pemrosesan PNG.

Jika Anda menggunakan Android Studio 4.0 atau yang lebih tinggi, cara terbaik untuk menyelidiki masalah performa build adalah dengan menggunakan Build Analyzer.

Selain itu, ada dua opsi untuk membuat profil build di luar Android Studio:

  1. Alat gradle-profiler mandiri, alat yang andal untuk analisis mendalam build Anda.

  2. Opsi --profile Gradle, alat praktis yang tersedia dari command line Gradle.

Menggunakan alat gradle-profiler mandiri

Untuk menemukan penyiapan project yang memberikan kecepatan build terbaik, Anda harus menggunakan Gradle profiler, alat untuk mengumpulkan informasi pembuatan profil dan tolok ukur untuk build Gradle. Dengan Gradle profiler, Anda dapat membuat skenario build dan menjalankannya beberapa kali, sehingga mencegah variasi yang tinggi di antara hasil dan memastikan hasil dapat direproduksi.

Mode tolok ukur harus digunakan untuk mengumpulkan informasi tentang build bersih dan inkremental, sedangkan mode pembuatan profil dapat digunakan untuk mengumpulkan informasi yang lebih terperinci tentang operasi, termasuk snapshot CPU.

Sejumlah konfigurasi penyiapan project untuk tolok ukur mencakup:

  • Versi plugin
  • Versi Gradle
  • Setelan JVM (ukuran heap, ukuran permgen, pembersihan sampah memori, dsb.)
  • Jumlah pekerja Gradle (org.gradle.workers.max)
  • Opsi per-plugin untuk mengoptimalkan performa lebih lanjut

Memulai

  • Instal profiler Gradle dengan mengikuti petunjuk ini
  • Jalankan: gradle-profiler --benchmark --project-dir <root-project> :app:assembleDebug

Tindakan ini akan membandingkan build yang sepenuhnya diperbarui dengan tolok ukur karena --benchmark menjalankan tugas beberapa kali tanpa mengubah project saat prosesnya berlangsung. Kemudian, laporan HTML akan dibuat dalam direktori profile-out/ yang akan menampilkan waktu build.

Ada skenario lain yang mungkin lebih berguna untuk diukur perbandingannya terhadap tolok ukur:

  • Perubahan kode dalam badan metode di class tempat Anda melakukan sebagian besar pekerjaan.
  • Perubahan API dalam modul yang digunakan di seluruh project. Meskipun lebih jarang dibandingkan perubahan pada kode Anda sendiri, hal ini memiliki dampak yang lebih besar dan berguna untuk mengukurnya.
  • Pengeditan tata letak untuk melakukan iterasi pada pekerjaan UI.
  • Pengeditan string untuk menyimulasikan penanganan pekerjaan terjemahan.
  • Bersihkan build untuk menyimulasikan perubahan pada build itu sendiri (misalnya, update plugin Android Gradle, update Gradle, atau pengeditan pada kode build Anda sendiri di bagian buildSrc).

Untuk mengukur perbandingan kasus penggunaan ini terhadap tolok ukur, Anda dapat membuat skenario yang akan digunakan untuk mendorong eksekusi gradle-profiler dan yang menerapkan perubahan yang sesuai ke sumber. Bagian berikut menjelaskan beberapa skenario umum.

Membuat profil berbagai setelan memori/CPU

Untuk mengukur perbandingan setelan memori dan CPU yang berbeda terhadap tolok ukur, Anda dapat membuat beberapa skenario yang menggunakan nilai berbeda untuk org.gradle.jvmargs. Misalnya, Anda dapat membuat skenario:

# <root-project>/scenarios.txt
clean_build_2gb_4workers {
    tasks = [":app:assembleDebug"]
    gradle-args = ["--max-workers=4"]
    jvm-args = ["-Xmx2048m"]
    cleanup-tasks = ["clean"]
}
clean_build_parallelGC {
    tasks = [":app:assembleDebug"]
    jvm-args = ["-XX:+UseParallelGC"]
    cleanup-tasks = ["clean"]
}

clean_build_G1GC_4gb {
    tasks = [":app:assembleDebug"]
    jvm-args = ["-Xmx4096m", "-XX:+UseG1GC"]
    cleanup-tasks = ["clean"]
}

Menjalankan gradle-profiler --benchmark --project-dir <root-project> --scenario-file scenarios.txt akan menjalankan tiga skenario, dan Anda dapat membandingkan waktu yang dibutuhkan :app:assembleDebug untuk setiap penyiapan ini.

Membuat profil berbagai versi plugin Gradle

Untuk mengetahui pengaruh perubahan versi plugin Gradle terhadap waktu build, buat skenario untuk membandingkannya dengan tolok ukur. Hal ini memerlukan persiapan untuk membuat versi plugin dapat dimasukkan dari skenario. Ubah build.gradle root:

# <root-project>/build.gradle
buildscript {
    def agpVersion = providers.systemProperty("agpVersion").forUseAtConfigurationTime().orNull ?: '4.1.0'

    ext.kotlin = providers.systemProperty('kotlinVersion').forUseAtConfigurationTime().orNull ?: '1.4.0'

    dependencies {
        classpath "com.android.tools.build:gradle:$agpVersion"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin"
    }
}

Kini Anda dapat menentukan versi plugin Android Gradle dan plugin Kotlin Gradle dari file skenario, dan meminta skenario menambahkan metode baru ke file sumber:

# <root-project>/scenarios.txt
non_abi_change_agp4.1.0_kotlin1.4.10 {
    tasks = [":app:assembleDebug"]
    apply-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
                              "app/src/main/java/com/example/your_app/your_code_file.kt"]
    System-properties {
      "agpVersion" = "4.1.0"
      "kotlinVersion" = "1.4.10"
}

non_abi_change_agp4.2.0_kotlin1.4.20 {
    tasks = [":app:assembleDebug"]
    apply-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
                              "app/src/main/java/com/example/your_app/your_code_file.kt"]
    System-properties {
      "agpVersion" = "4.2.0-alpha16"
      "kotlinVersion" = "1.4.20"
}

Membuat profil build inkremental

Mayoritas build bersifat inkremental, sehingga menjadi salah satu skenario yang paling penting untuk profil. Gradle Profiler memiliki dukungan ekstensif untuk membuat profil build inkremental. Fitur ini dapat menerapkan perubahan pada file sumber secara otomatis dengan mengubah isi metode, menambahkan metode baru, atau mengubah resource tata letak atau resource string. Misalnya, Anda dapat membuat skenario inkremental seperti ini:

# <root-project>/scenarios.txt
non_abi_change {
    tasks = [":app:assembleDebug"]
    apply-non-abi-change-to = ["app/src/main/java/com/example/your_app/your_code_file.java,
                              "app/src/main/java/com/example/your_app/your_code_file.kt"]
}

abi_change {
    tasks = [":app:assembleDebug"]
    apply-abi-change-to = ["app/src/main/java/com/example/your_app/your_code_file.java,
                              "app/src/main/java/com/example/your_app/your_code_file.kt"]
}

layout_change {
    tasks = [":app:assembleDebug"]
    apply-android-layout-change-to = "app/src/main/res/your_layout_file.xml"
}
string_resource_change {
    tasks = [":app:assembleDebug"]
    apply-android-resource-value-change-to = "app/src/main/res/values/strings.xml"
}

Menjalankan gradle-profiler --benchmark --project-dir <root-project> --scenario-file scenarios.txt akan menghasilkan laporan HTML dengan data tolok ukur.

Anda dapat menggabungkan skenario inkremental dengan setelan lain, seperti ukuran heap, jumlah pekerja, atau versi Gradle:

# <root-project>/scenarios.txt
non_abi_change_4g {
    tasks = [":app:assembleDebug"]
    apply-non-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
                              "app/src/main/java/com/example/your_app/your_code_file.kt"]
    jvm-args = ["-Xmx4096m"]
}

non_abi_change_4g_8workers {
    tasks = [":app:assembleDebug"]
    apply-non-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
                              "app/src/main/java/com/example/your_app/your_code_file.kt"]
    jvm-args = ["-Xmx4096m"]
    gradle-args = ["--max-workers=8"]
}

non_abi_change_3g_gradle67 {
    tasks = [":app:assembleDebug"]
    apply-non-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
                              "app/src/main/java/com/example/your_app/your_code_file.kt"]
    jvm-args = ["-Xmx3072m"]
    version = ["6.7"]
}

Membuat profil build bersih

Untuk mengukur perbandingan build bersih terhadap tolok ukur, Anda dapat membuat skenario yang akan digunakan untuk mendorong eksekusi profiler gradle:

# <root-project>/scenarios.txt
clean_build {
    tasks = [":app:assembleDebug"]
    cleanup-tasks = ["clean"]
}

Untuk menjalankan skenario ini, gunakan perintah berikut:

gradle-profiler --benchmark --project-dir <root-project> --scenario-file scenarios.txt

Menggunakan opsi --profile Gradle

Untuk membuat dan melihat profil build dari command line Gradle, lakukan langkah-langkah berikut:

  1. Buka terminal command line di root project Anda.

  2. Lakukan clean build dengan memasukkan perintah berikut. Saat membuat profil build, Anda harus menjalankan clean build di antara setiap build yang Anda profilkan, karena Gradle melewati tugas saat input tugas (misalnya kode sumber) tidak berubah. Dengan demikian, build kedua tanpa perubahan input selalu berjalan lebih cepat karena tugas tidak dijalankan ulang. Jadi, menjalankan tugas clean di antara build akan memastikan Anda membuat profil proses build lengkap.

    // On Mac or Linux, run the Gradle wrapper using "./gradlew".
    gradlew clean
    
  3. Jalankan build debug salah satu ragam produk Anda, seperti ragam "dev", dengan flag berikut:

    gradlew --profile --offline --rerun-tasks assemble<var>Flavor</var>Debug
    
    • --profile: Mengaktifkan pembuatan profil.

    • --offline: Menonaktifkan Gradle agar tidak mengambil dependensi online. Hal ini memastikan bahwa penundaan apa pun yang disebabkan oleh Gradle yang mencoba mengupdate dependensi Anda tidak mengganggu data pembuatan profil. Anda harus sudah mem-build project sekali untuk memastikan Gradle telah mendownload dan meng-cache dependensi Anda.

    • --rerun-tasks: Memaksa Gradle untuk menjalankan ulang semua tugas dan mengabaikan pengoptimalan tugas apa pun.

  4. Setelah build selesai, gunakan jendela Project untuk membuka direktori project-root/build/reports/profile/ (seperti yang ditunjukkan pada gambar 1).

    Gambar 1. Tampilan project yang menunjukkan lokasi laporan profil.

  5. Klik kanan file profile-timestamp.html, lalu pilih Open in Browser > Default. Laporan akan terlihat mirip dengan yang ditunjukkan pada gambar 2. Anda dapat memeriksa setiap tab dalam laporan untuk mempelajari build Anda, seperti tab Task Execution yang menunjukkan durasi yang diperlukan Gradle untuk menjalankan setiap tugas build.

    Gambar 2. Menampilkan laporan di browser.

  6. Opsional: Sebelum melakukan perubahan apa pun pada project atau konfigurasi build, ulangi perintah di langkah 3, tetapi hapus flag --rerun-tasks. Karena Gradle berupaya menghemat waktu dengan tidak menjalankan ulang tugas yang inputnya tidak berubah (ini ditunjukkan sebagai UP-TO-DATE di tab Task Execution laporan, seperti yang ditunjukkan pada gambar 3), Anda dapat mengidentifikasi tugas mana yang melakukan pekerjaan saat seharusnya tidak dilakukan. Misalnya, jika :app:processDevUniversalDebugManifest tidak ditandai sebagai UP-TO-DATE, hal ini mungkin menunjukkan bahwa konfigurasi build Anda memperbarui manifes secara dinamis dengan setiap build. Namun, beberapa tugas harus dijalankan selama setiap build, seperti :app:checkDevDebugManifest.

    Gambar 3. Menampilkan hasil eksekusi tugas.

Setelah memiliki laporan profil build, Anda dapat mulai mencari peluang pengoptimalan dengan memeriksa informasi di setiap tab laporan. Beberapa setelan build memerlukan eksperimen karena manfaatnya mungkin berbeda antara project dan workstation. Misalnya, project dengan codebase besar dapat memanfaatkan penyingkatan kode untuk menghapus kode yang tidak digunakan dan memperkecil ukuran aplikasi. Namun, project yang lebih kecil mungkin akan lebih diuntungkan dengan menonaktifkan penyingkatan kode sama sekali. Selain itu, meningkatkan ukuran heap Gradle (menggunakan org.gradle.jvmargs) dapat berdampak negatif pada performa di mesin dengan memori rendah.

Setelah membuat perubahan pada konfigurasi build, amati hasil perubahan Anda dengan mengulangi langkah-langkah sebelumnya dan membuat profil build baru. Misalnya, gambar 4 menunjukkan laporan untuk aplikasi contoh yang sama setelah menerapkan beberapa pengoptimalan dasar yang dijelaskan di halaman ini.

Gambar 4. Menampilkan laporan baru setelah mengoptimalkan kecepatan build.