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 waktu yang diperlukan Gradle untuk mengeksekusi setiap fase siklus proses build dan setiap tugas build. Misalnya, jika profil build Anda menunjukkan bahwa Gradle menghabiskan terlalu banyak waktu untuk mengonfigurasi project, ini mungkin menandakan bahwa Anda perlu mengeluarkan logika build kustom dari fase konfigurasi. Selain itu, jika tugas mergeDevDebugResources menghabiskan banyak waktu build, ini mungkin menandakan 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 canggih untuk menganalisis build secara mendalam.

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

Menggunakan alat gradle-profiler mandiri

Untuk menemukan konfigurasi project yang menghadirkan kecepatan build terbaik, Anda harus menggunakan profiler Gradle, yaitu alat untuk mengumpulkan informasi pembuatan profil dan tolok ukur untuk build Gradle. Profiler Grader memungkinkan Anda membuat skenario build dan menjalankannya beberapa kali, mencegah varian tinggi pada hasil, dan memastikan hasil dapat direproduksi.

Mode tolok ukur harus digunakan untuk mengumpulkan informasi tentang build bersih dan inkremental, sementara mode pembuatan profil dapat digunakan untuk mengumpulkan informasi yang lebih terperinci tentang proses berjalan, 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.
  • Build bersih untuk menyimulasikan perubahan pada build itu sendiri (misalnya, Update plugin Android Gradle, update Gradle, atau pengeditan kode build Anda sendiri dalam 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. Anda dapat memeriksa beberapa skenario umum di bawah ini.

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. Profiler Gradle memiliki dukungan yang luas untuk membuat profil build inkremental. Profiler Gradle dapat menerapkan perubahan ke file sumber secara otomatis dengan mengubah isi metode, menambahkan metode baru, atau mengubah 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 &lt;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.
  2. Jalankan 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 dapat memastikan bahwa Anda membuat profil proses build secara penuh.
    // On Mac or Linux, run the Gradle wrapper using "./gradlew".
    gradlew clean
    
  3. Jalankan build debug untuk salah satu ragam produk Anda, misalnya ragam "dev", dengan tanda berikut:
    gradlew --profile --offline --rerun-tasks assembleFlavorDebug
    
    • --profile: Mengaktifkan pembuatan profil.
    • --offline: Menonaktifkan Gradle agar tidak mengambil dependensi online. Ini memastikan bahwa penundaan apa pun yang disebabkan oleh upaya Gradle untuk mengupdate dependensi tidak akan mengganggu data profiling Anda. Sebaiknya Anda sudah membuat project satu kali untuk memastikan bahwa Gradle telah mendownload dan meng-cache dependensi Anda.
    • --rerun-tasks: Memaksa Gradle untuk menjalankan ulang semua tugas dan mengabaikan pengoptimalan tugas apa pun.
  4. Gambar 1. Tampilan project yang menunjukkan lokasi laporan profil.

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

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

    Gambar 2. Menampilkan laporan di browser.

  6. Opsional: Sebelum membuat perubahan pada project atau konfigurasi build, ulangi perintah di langkah 3, tetapi hilangkan tanda --rerun-tasks. Karena Gradle mencoba menghemat waktu dengan tidak mengeksekusi ulang tugas yang inputnya tidak berubah (ini ditandai sebagai UP-TO-DATE di tab Task Execution dalam laporan, seperti yang ditunjukkan pada gambar 3), Anda dapat mengidentifikasi tugas apa saja yang melakukan pekerjaan padahal seharusnya tidak. Misalnya, jika :app:processDevUniversalDebugManifest tidak ditandai sebagai UP-TO-DATE, ini mungkin berarti bahwa konfigurasi build Anda memperbarui manifes secara dinamis dengan setiap build yang dirilis. Namun, beberapa tugas perlu dijalankan pada setiap pembuatan build, seperti :app:checkDevDebugManifest.

    Gambar 3. Menampilkan hasil eksekusi tugas.

Setelah mendapatkan laporan profil build, sekarang Anda dapat mulai mencari peluang pengoptimalan dengan memeriksa informasi di setiap tab laporan. Beberapa setelan build memerlukan eksperimen karena manfaatnya mungkin berbeda untuk project dan workstation yang berbeda. Misalnya, project dengan codebase berukuran besar mungkin dapat memperoleh manfaat dari penyingkatan kode untuk menghapus kode yang tidak terpakai dan mengecilkan ukuran aplikasi. Namun, project yang lebih kecil mungkin lebih diuntungkan dengan menonaktifkan penyingkatan kode sepenuhnya. Selain itu, meningkatkan ukuran heap Gradle (menggunakan org.gradle.jvmargs) mungkin berdampak negatif pada performa mesin yang bermemori rendah.

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

Gambar 4. Menampilkan laporan baru setelah mengoptimalkan kecepatan build.