Mengoptimalkan kecepatan build

Waktu build yang lama memperlambat proses pengembangan. Halaman ini menyediakan beberapa teknik untuk membantu mengatasi kendala pada kecepatan build.

Proses yang biasa dilakukan untuk meningkatkan kecepatan build aplikasi Anda adalah sebagai berikut:

  1. Mengoptimalkan konfigurasi build dengan menjalankan beberapa langkah yang langsung memberikan manfaat pada sebagian besar project Android Studio.
  2. Membuat profil build untuk mengidentifikasi dan mendiagnosis beberapa kendala rumit yang mungkin berlaku spesifik pada project atau workstation Anda.

Saat mengembangkan aplikasi, lakukan deployment ke perangkat yang menjalankan Android 7.0 (API level 24) atau versi lebih tinggi, jika memungkinkan. Platform Android versi baru menggunakan mekanisme yang lebih baik untuk mendorong update ke aplikasi Anda, seperti Android Runtime (ART) dan dukungan native untuk beberapa file DEX.

Catatan: Setelah membuat clean build pertama, Anda mungkin merasa bahwa build selanjutnya, baik clean maupun inkremental, berperforma jauh lebih cepat bahkan tanpa menggunakan pengoptimalan apa pun yang dijelaskan pada halaman ini. Hal ini dikarenakan daemon Gradle memiliki periode "pemanasan" untuk meningkatkan performa—serupa dengan proses JVM lainnya.

Mengoptimalkan konfigurasi build Anda

Ikuti tips berikut untuk meningkatkan kecepatan build project Android Studio Anda.

Menjaga alat Anda agar selalu terupdate

Alat Android menerima pengoptimalan build dan fitur baru dengan hampir setiap update. Beberapa tips pada halaman ini diberikan dengan asumsi bahwa Anda menggunakan versi terbaru. Untuk memanfaatkan pengoptimalan terbaru, selalu update:

Menggunakan KSP, bukan kapt

Alat Pemrosesan Anotasi Kotlin (kapt) jauh lebih lambat daripada Pemroses Simbol Kotlin (KSP). Jika Anda menulis sumber Kotlin teranotasi dan menggunakan alat yang memproses anotasi (seperti Room) yang mendukung KSP, Anda dapat bermigrasi ke KSP.

Menghindari mengompilasi sumber daya yang tidak perlu

Hindari mengompilasi dan memaketkan resource yang tidak sedang Anda uji seperti pelokalan bahasa tambahan dan resource kepadatan layar. Sebaliknya, hanya tentukan satu resource bahasa dan kepadatan layar untuk ragam "dev", seperti yang ditunjukkan pada contoh berikut:

Groovy

android {
    ...
    productFlavors {
        dev {
            ...
            // The following configuration limits the "dev" flavor to using
            // English stringresources and xxhdpi screen-density resources.
            resourceConfigurations "en", "xxhdpi"
        }
        ...
    }
}

Kotlin

android {
    ...
    productFlavors {
        create("dev") {
            ...
            // The following configuration limits the "dev" flavor to using
            // English stringresources and xxhdpi screen-density resources.
            resourceConfigurations("en", "xxhdpi")
        }
        ...
    }
}

Bereksperimen dengan menempatkan Portal Plugin Gradle di akhir

Di Android, semua plugin berada dalam repositori google() dan mavenCentral(). Namun, build Anda mungkin memerlukan plugin pihak ketiga yang di-resolve menggunakan layanan gradlePluginPortal().

Gradle menelusuri repositori sesuai urutan yang dideklarasikan, sehingga performa build akan meningkat jika repositori yang tercantum pertama kali berisi sebagian besar plugin. Oleh karena itu, lakukan eksperimen dengan entri gradlePluginPortal() dengan menempatkannya terakhir di blok repositori dalam file settings.gradle Anda. Pada umumnya, hal ini meminimalkan jumlah penelusuran plugin yang berlebihan dan meningkatkan kecepatan build Anda.

Untuk informasi selengkapnya tentang cara Gradle menjelajahi beberapa repositori, lihat Mendeklarasikan beberapa repositori dalam dokumentasi Gradle.

Menggunakan nilai konfigurasi build statis dengan build debug Anda

Selalu gunakan nilai statis untuk properti yang dimasukkan ke file manifes atau file resource untuk jenis build debug Anda.

Penggunaan kode versi dinamis, nama versi, resource, atau logika build lain yang mengubah file manifes memerlukan build aplikasi lengkap setiap kali Anda ingin menjalankan perubahan, meskipun perubahan sebenarnya mungkin hanya memerlukan hot swap. Jika konfigurasi build Anda memerlukan properti dinamis semacam itu, pisahkan properti tersebut ke varian build rilis Anda dan pertahankan nilai statis untuk build debug, seperti yang ditampilkan pada contoh berikut:

  ...
  // Use a filter to apply onVariants() to a subset of the variants.
  onVariants(selector().withBuildType("release")) { variant ->
      // Because an app module can have multiple outputs when using multi-APK, versionCode
      // is only available on the variant output.
      // Gather the output when we are in single mode and there is no multi-APK.
      val mainOutput = variant.outputs.single { it.outputType == OutputType.SINGLE }

      // Create the version code generating task.
      val versionCodeTask = project.tasks.register("computeVersionCodeFor${variant.name}", VersionCodeTask::class.java) {
          it.outputFile.set(project.layout.buildDirectory.file("versionCode${variant.name}.txt"))
      }

      // Wire the version code from the task output.
      // map will create a lazy Provider that:
      // 1. Runs just before the consumer(s), ensuring that the producer (VersionCodeTask) has run
      //    and therefore the file is created.
      // 2. Contains task dependency information so that the consumer(s) run after the producer.
      mainOutput.versionCode.set(versionCodeTask.flatMap { it.outputFile.map { it.asFile.readText().toInt() } })
  }
  ...

  abstract class VersionCodeTask : DefaultTask() {

    @get:OutputFile
    abstract val outputFile: RegularFileProperty

    @TaskAction
    fun action() {
        outputFile.get().asFile.writeText("1.1.1")
    }
  }

Lihat urutan langkah setVersionsFromTask di GitHub untuk mempelajari cara menetapkan kode versi dinamis dalam project Anda.

Menggunakan versi dependensi statis

Saat mendeklarasikan dependensi dalam file build.gradle, hindari penggunaan nomor versi dinamis (yang memiliki tanda plus di bagian akhir, seperti 'com.android.tools.build:gradle:2.+'). Menggunakan nomor versi dinamis dapat menyebabkan update versi yang tidak terduga, kesulitan mengatasi perbedaan versi, dan build lebih lambat yang disebabkan oleh pemeriksaan update oleh Gradle. Sebagai gantinya, gunakan nomor versi statis.

Membuat modul library

Temukan kode dalam aplikasi Anda yang dapat diubah menjadi modul library Android. Memodulasi kode dengan cara ini memungkinkan sistem build untuk hanya mengompilasi modul yang Anda ubah, dan meng-cache output tersebut untuk build mendatang. Modularisasi juga membuat eksekusi project paralel jadi lebih efektif saat Anda mengaktifkan pengoptimalan tersebut.

Membuat tugas untuk logika build khusus

Setelah membuat profil build, jika profil build menunjukkan bahwa sebagian besar waktu build yang lama dihabiskan di fase **Mengonfigurasi Project**, periksa skrip build.gradle dan cari kode untuk disertakan dalam tugas Gradle kustom. Dengan memindahkan beberapa logika build ke dalam tugas, Anda akan membantu memastikan bahwa tugas hanya berjalan jika diperlukan, hasilnya dapat di-cache untuk build selanjutnya, dan logika build tersebut dapat dijalankan secara paralel jika Anda mengaktifkan eksekusi project paralel. Guna mempelajari lebih lanjut tentang tugas untuk logika build kustom, baca dokumentasi Gradle resmi.

Tips: Jika build Anda menyertakan banyak tugas kustom, Anda mungkin perlu memecah file build.gradle dengan membuat class tugas kustom. Tambahkan class Anda ke direktori project-root/buildSrc/src/main/groovy/; Gradle secara otomatis menyertakan class tersebut dalam classpath untuk semua file build.gradle di project Anda.

Mengonversi gambar ke WebP

WebP adalah format file gambar yang memberikan kompresi lossy (seperti JPEG) serta transparansi (seperti PNG). WebP dapat memberikan kompresi yang lebih baik daripada JPEG atau PNG.

Mengurangi ukuran file gambar tanpa perlu menjalankan kompresi waktu build dapat mempercepat build, terutama jika aplikasi Anda menggunakan banyak referensi gambar. Namun, Anda mungkin akan melihat sedikit peningkatan penggunaan CPU perangkat saat melakukan dekompresi gambar WebP. Gunakan Android Studio untuk mengonversi gambar ke WebP dengan mudah.

Menonaktifkan pemrosesan PNG

Jika tidak mengonversi gambar PNG ke WebP, Anda tetap dapat mempercepat build dengan menonaktifkan kompresi gambar otomatis setiap kali mem-build aplikasi.

Jika Anda menggunakan plugin Android 3.0.0 atau yang lebih tinggi, pemrosesan PNG dinonaktifkan secara default hanya untuk jenis build "debug". Guna menonaktifkan pengoptimalan ini untuk jenis build lainnya, tambahkan kode berikut ini ke file build.gradle Anda:

Groovy

android {
    buildTypes {
        release {
            // Disables PNG crunching for the "release" build type.
            crunchPngs false
        }
    }
}

Kotlin

android {
    buildTypes {
        getByName("release") {
            // Disables PNG crunching for the "release" build type.
            isCrunchPngs = false
        }
    }
}

Karena jenis build atau ragam produk tidak menentukan properti ini, Anda perlu menyetel properti ini secara manual ke true saat membuat versi rilis aplikasi Anda.

Bereksperimen dengan pembersih sampah memori paralel JVM

Performa build dapat ditingkatkan dengan mengonfigurasi pembersih sampah memori JVM optimal yang digunakan oleh Gradle. Meskipun JDK 8 dikonfigurasi untuk menggunakan pembersih sampah memori paralel secara default, JDK 9 dan yang lebih tinggi dikonfigurasi untuk menggunakan pembersih sampah memori G1.

Untuk meningkatkan performa build, sebaiknya uji build Gradle Anda dengan pembersih sampah memori paralel. Di gradle.properties tetapkan hal berikut:

org.gradle.jvmargs=-XX:+UseParallelGC

Jika ada opsi lain yang telah ditetapkan di kolom ini, tambahkan opsi baru:

org.gradle.jvmargs=-Xmx1536m -XX:+UseParallelGC

Untuk mengukur kecepatan build dengan konfigurasi yang berbeda, lihat Membuat profil build Anda.

Meningkatkan ukuran heap JVM

Jika Anda mengamati proses build berjalan lambat, terlebih jika pembersihan sampah memori menghabiskan lebih dari 15% waktu build di hasil Build Analyzer , Anda harus meningkatkan ukuran heap Java Virtual Machine (JVM). Dalam file gradle.properties, tetapkan batas ke 4, 6, atau 8 gigabyte seperti yang ditunjukkan pada contoh berikut:

org.gradle.jvmargs=-Xmx6g

Kemudian, lakukan pengujian untuk meningkatkan kecepatan build. Cara termudah untuk menentukan ukuran heap yang optimal adalah dengan meningkatkan batas dalam jumlah kecil, lalu mengujinya untuk memastikan peningkatan kecepatan build sudah memadai.

Jika Anda juga menggunakan pembersih sampah memori paralel JVM, seluruh baris akan terlihat seperti ini:

org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g

Anda dapat menganalisis error memori JVM dengan mengaktifkan flag HeapDumpOnOutOfMemoryError . Dengan melakukan tindakan ini, JVM akan menghasilkan heap dump saat memori habis.

Menggunakan class R non-transitif

Gunakan class R non-transitif agar build untuk aplikasi dengan beberapa modul dapat menjadi lebih cepat. Cara ini membantu mencegah duplikasi resource dengan memastikan bahwa class R setiap modul hanya berisi referensi ke resource-nya sendiri, tanpa mengambil referensi dari dependensinya. Dengan demikian, build akan menjadi lebih cepat dan Anda dapat menghindari kompilasi terkait. Ini adalah perilaku default di plugin Android Gradle 8.0.0 dan yang lebih tinggi.

Mulai dari Android Studio Bumblebee, class R non-transitif untuk project baru akan diaktifkan secara default. Untuk project yang dibuat dengan Android Studio versi sebelumnya, update project agar dapat menggunakan class R non-transitif dengan membuka Refactor > Migrate to Non-Transitive R Classes.

Untuk mempelajari resource aplikasi dan class R lebih lanjut, lihat Ringkasan resource aplikasi.

Menggunakan class R non-konstanta

Gunakan kolom class R non-konstanta dalam aplikasi dan pengujian untuk meningkatkan inkrementalitas kompilasi Java dan memungkinkan penyingkatan resource yang lebih tepat. Kolom class R selalu tidak konstan untuk library, karena resource diberi nomor saat memaketkan APK untuk aplikasi atau pengujian yang bergantung pada library tersebut. Ini adalah perilaku default di Plugin Android Gradle 8.0.0 dan yang lebih tinggi.

Menonaktifkan flag Jetifier

Sebagian besar project menggunakan library AndroidX secara langsung. Oleh karena itu, Anda dapat menghapus flag Jetifier untuk performa build yang lebih baik. Untuk menghapus flag Jetifier, tetapkan android.enableJetifier=false dalam file gradle.properties Anda.

Build Analyzer dapat melakukan pemeriksaan untuk memeriksa apakah flag dapat dihapus dengan aman agar project Anda memiliki performa build yang lebih baik dan dapat bermigrasi dari Android Support library yang tidak dikelola. Untuk mempelajari Build Analyzer lebih lanjut, lihat Memecahkan masalah performa build.

Menggunakan cache konfigurasi

Cache konfigurasi memungkinkan Gradle mencatat informasi tentang grafik tugas build dan menggunakannya kembali dalam build berikutnya, sehingga Gradle tidak perlu mengonfigurasi ulang seluruh build.

Untuk mengaktifkan cache konfigurasi, ikuti langkah-langkah berikut:

  1. Periksa apakah semua plugin project kompatibel.

    Gunakan Build Analyzer untuk memeriksa apakah project Anda kompatibel dengan cache konfigurasi. Build Analyzer menjalankan urutan build pengujian untuk menentukan apakah fitur ini dapat diaktifkan untuk project. Lihat masalah #13490 untuk daftar plugin yang didukung.

  2. Tambahkan kode berikut ke file gradle.properties:

      org.gradle.configuration-cache=true
      # Use this flag carefully, in case some of the plugins are not fully compatible.
      org.gradle.configuration-cache.problems=warn

Jika cache konfigurasi diaktifkan, output build akan menampilkan Calculating task graph as no configuration cache is available for tasks saat pertama kali Anda menjalankan project. Selama proses berikutnya, output build akan mengatakan Reusing configuration cache.

Untuk mempelajari cache konfigurasi lebih lanjut, lihat postingan blog Mendalami cache konfigurasi dan dokumentasi Gradle tentang cache konfigurasi.

Masalah cache konfigurasi diperkenalkan di Gradle 8.1 dan Plugin Android Gradle 8.1

Cache konfigurasi menjadi stabil di Gradle 8.1, dan memperkenalkan pelacakan API file. Panggilan seperti File.exists(), File.isDirectory(), dan File.list() direkam oleh Gradle untuk melacak file input konfigurasi.

Plugin Android Gradle (AGP) 8.1 menggunakan File API ini untuk beberapa file yang tidak boleh dianggap Gradle sebagai input cache. Tindakan ini akan memicu pembatalan validasi cache tambahan saat digunakan dengan Gradle 8.1 dan yang lebih baru, sehingga memperlambat performa build. Hal berikut diperlakukan sebagai input cache di AGP 8.1:

Input Issue Tracker Diperbaiki pada
$GRADLE_USER_HOME/android/FakeDependency.jar Masalah #289232054 AGP 8.2
output cmake Masalah #287676077 AGP 8.2
$GRADLE_USER_HOME/.android/analytics.settings Masalah #278767328 AGP 8.3

Jika menggunakan API tersebut atau plugin yang menggunakan API ini, Anda mungkin akan mengalami regresi waktu build, karena beberapa logika build yang menggunakan API ini dapat memicu pembatalan validasi cache tambahan. Lihat Peningkatan pada pelacakan input konfigurasi build untuk membahas pola ini dan cara memperbaiki logika build, atau menonaktifkan pelacakan API file untuk sementara.