Mengoptimalkan kecepatan build Anda

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

Proses yang biasa dilakukan untuk meningkatkan kecepatan build 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, sebaiknya Anda melakukan deployment ke perangkat yang menjalankan Android 7.0 (API level 24) atau yang lebih tinggi, jika memungkinkan. Versi platform Android yang lebih baru mengimplementasikan 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—clean dan incremental—berperforma jauh lebih cepat (bahkan tanpa menggunakan pengoptimalan apa pun yang dijelaskan pada halaman ini). Hal ini karena 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 fitur agar selalu terupdate

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

Membuat varian build untuk pengembangan

Banyak dari konfigurasi yang Anda perlukan saat menyiapkan aplikasi untuk dirilis sebenarnya tidak diperlukan selama proses pengembangan aplikasi. Mengaktifkan proses build yang tidak diperlukan akan memperlambat incremental dan clean build Anda, jadi konfigurasi varian build yang mempertahankan konfigurasi build yang memang diperlukan saat mengembangkan aplikasi. Contoh berikut membuat ragam "dev" dan "prod" (untuk konfigurasi versi rilis Anda):

    android {
      ...
      defaultConfig {...}
      buildTypes {...}
      productFlavors {
        // When building a variant that uses this flavor, the following configurations
        // override those in the defaultConfig block.
        dev {
          // To avoid using legacy multidex when building from the command line,
          // set minSdkVersion to 21 or higher. When using Android Studio 2.3 or higher,
          // the build automatically avoids legacy multidex when deploying to a device running
          // API level 21 or higher—regardless of what you set as your minSdkVersion.
          minSdkVersion 21
          versionNameSuffix "-dev"
          applicationIdSuffix '.dev'
        }

        prod {
          // If you've configured the defaultConfig block for the release version of
          // your app, you can leave this block empty and Gradle uses configurations in
          // the defaultConfig block instead. You still need to create this flavor.
          // Otherwise, all variants use the "dev" flavor configurations.
        }
      }
    }
    

Jika konfigurasi build Anda sudah menggunakan ragam produk untuk membuat versi yang berbeda dari aplikasi Anda, Anda dapat menggabungkan konfigurasi "dev" dan "prod" dengan ragam tersebut menggunakan dimensi ragam. Misalnya, jika Anda sudah mengonfigurasi ragam "demo" dan "full", Anda dapat menggunakan contoh konfigurasi berikut untuk membuat gabungan ragam, seperti "devDemo" dan "prodFull":

    android {
      ...
      defaultConfig {...}
      buildTypes {...}

      // Specifies the flavor dimensions you want to use. The order in which you
      // list each dimension determines its priority, from highest to lowest,
      // when Gradle merges variant sources and configurations. You must assign
      // each product flavor you configure to one of the flavor dimensions.

      flavorDimensions "stage", "mode"

      productFlavors {
        dev {
          dimension "stage"
          minSdkVersion 21
          versionNameSuffix "-dev"
          applicationIdSuffix '.dev'
          ...
        }

        prod {
          dimension "stage"
          ...
        }

        demo {
          dimension "mode"
          ...
        }

        full {
          dimension "mode"
          ...
        }
      }
    }
    

Mengaktifkan sinkronisasi project varian tunggal

Menyinkronkan project dengan konfigurasi build merupakan langkah penting yang akan memungkinkan Android Studio memahami struktur project Anda. Namun, untuk project besar, sinkronisasi ini dapat memerlukan waktu lama. Jika project Anda menggunakan banyak varian build, sekarang Anda dapat mengoptimalkan sinkronisasi project dengan membatasinya hanya ke varian yang saat ini Anda pilih.

Anda harus menggunakan Android Studio 3.3 atau yang lebih tinggi dengan Android Gradle Plugin 3.3.0 atau yang lebih baru untuk mengaktifkan pengoptimalan ini. Pengoptimalan diaktifkan secara default pada semua project.

Untuk mengaktifkan pengoptimalan ini secara manual, klik File > Settings > Experimental > Gradle (Android Studio > Preferences > Experimental > Gradle pada Mac), lalu centang kotak Only sync the active variant.

Catatan: Pengoptimalan ini mendukung sepenuhnya project yang menggunakan bahasa Java dan C++, serta menyediakan dukungan untuk Kotlin. Saat mengaktifkan pengoptimalan untuk project dengan konten Kotlin, sinkronisasi Gradle akan melakukan fallback untuk menggunakan varian penuh secara internal.

Menghindari kompilasi resource yang tidak perlu

Hindari mengompilasi dan mengemas resource yang tidak sedang Anda uji (seperti pelokalan bahasa tambahan dan resource kepadatan layar). Anda dapat melakukannya dengan hanya menetapkan satu resource bahasa dan kepadatan layar untuk ragam "dev", seperti yang ditunjukkan pada contoh berikut:

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

Menonaktifkan Crashlytics untuk build debug Anda

Jika Anda tidak perlu menjalankan laporan Crashlytics, percepat proses build debug Anda dengan menonaktifkan plugin ini dengan cara berikut:

    android {
      ...
      buildTypes {
        debug {
          ext.enableCrashlytics = false
        }
    }
    

Anda juga harus menonaktifkan kit Crashlytics saat runtime untuk build debug dengan mengubah cara Anda menginisialiasi dukungan Fabric di aplikasi, seperti yang ditunjukkan di bawah ini:

Kotlin

    // Initializes Fabric for builds that don't use the debug build type.
    Crashlytics.Builder()
            .core(CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build())
            .build()
            .also { crashlyticsKit ->
                Fabric.with(this, crashlyticsKit)
            }
    

Java

    // Initializes Fabric for builds that don't use the debug build type.
    Crashlytics crashlyticsKit = new Crashlytics.Builder()
        .core(new CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build())
        .build();

    Fabric.with(this, crashlyticsKit);
    

Menonaktifkan pembuatan ID build otomatis

Jika Anda ingin menggunakan Crashlytics dengan build debug, Anda tetap bisa mempercepat incremental build dengan mencegah Crashlytics mengupdate resource aplikasi dengan ID build uniknya sendiri selama setiap proses build. Karena ID build ini disimpan dalam file resource yang diacu oleh manifes, penonaktifan pembuatan ID build otomatis juga memungkinkan Anda untuk menggunakan Terapkan Perubahan bersama Crashlytics untuk build debug Anda.

Agar Crashlytics tidak terus-menerus mengupdate ID build-nya, tambahkan berikut ini ke file build.gradle Anda:

    android {
      ...
      buildTypes {
        debug {
          ext.alwaysUpdateBuildId = false
        }
    }
    

Untuk mengetahui cara mengoptimalkan build selagi menggunakan Crashlytics selengkapnya, baca dokumentasi resmi.

Menggunakan nilai konfigurasi build statis dengan build debug Anda

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

Misalnya, penggunaan kode versi dinamis, nama versi, resource, atau logika build lain yang mengubah file manifes, memerlukan build APK lengkap setiap kali Anda ingin menjalankan perubahan—meskipun perubahan sebenarnya mungkin hanya memerlukan hot swap. Jika konfigurasi build Anda memerlukan properti dinamis semacam itu, maka pisahkan konfigurasi tersebut ke varian build rilis Anda, dan pertahankan nilai statis untuk build debug, seperti yang ditunjukkan pada file build.gradle di bawah ini.

    int MILLIS_IN_MINUTE = 1000 * 60
    int minutesSinceEpoch = System.currentTimeMillis() / MILLIS_IN_MINUTE

    android {
        ...
        defaultConfig {
            // Making either of these two values dynamic in the defaultConfig will
            // require a full APK build and reinstallation because the AndroidManifest.xml
            // must be updated.
            versionCode 1
            versionName "1.0"
            ...
        }

        // The defaultConfig values above are fixed, so your incremental builds don't
        // need to rebuild the manifest (and therefore the whole APK, slowing build times).
        // But for release builds, it's okay. So the following script iterates through
        // all the known variants, finds those that are "release" build types, and
        // changes those properties to something dynamic.
        applicationVariants.all { variant ->
            if (variant.buildType.name == "release") {
                variant.mergedFlavor.versionCode = minutesSinceEpoch;
                variant.mergedFlavor.versionName = minutesSinceEpoch + "-" + variant.flavorName;
            }
        }
    }
    

Menggunakan versi dependensi statis

Saat mendeklarasikan dependensi dalam file build.gradle, hindari penggunaan nomor versi dengan tanda plus di bagian akhir, seperti 'com.android.tools.build:gradle:2..+' Penggunaan 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, sebaiknya Anda menggunakan nomor versi statis/hard-code.

Mengaktifkan mode offline

Jika sambungan jaringan Anda lambat, waktu build mungkin akan terkena dampak saat Gradle mencoba menggunakan resource jaringan untuk mengatasi dependensi. Anda dapat memberi tahu Gradle agar tidak menggunakan resource jaringan dengan hanya menggunakan artefak yang telah di-cache secara lokal.

Untuk menggunakan Gradle secara offline saat membuat build dengan Android Studio, lakukan langkah-langkah berikut:

  1. Buka jendela Preferences dengan mengklik File > Settings (pada Mac, Android Studio > Preferences).
  2. Di panel sebelah kiri, klik Build, Execution, Deployment > Gradle.
  3. Centang kotak Offline work.
  4. Klik Apply atau OK.

Jika Anda membuat build dari command line, teruskan opsi --offline.

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. Tindakan ini juga membuat eksekusi project paralel jadi lebih efektif (saat Anda mengaktifkan pengoptimalan tersebut).

Membuat tugas untuk logika build kustom

Setelah membuat profil build, jika fase "Mengonfigurasi Project" ternyata menghabiskan waktu build yang cukup lama, periksa skrip build.gradle dan temukan kode yang bisa Anda sertakan dalam tugas Gradle kustom. Dengan memindahkan beberapa logika build ke dalam sebuah tugas, kode hanya akan dijalankan saat diperlukan, hasilnya dapat di-cache untuk build selanjutnya, dan logika build tersebut dapat dijalankan secara paralel (jika Anda menjalankan eksekusi project paralel). Untuk mempelajari lebih lanjut, baca dokumentasi resmi Gradle.

Tips: Jika build Anda menyertakan banyak tugas kustom, Anda mungkin perlu memecah file build.gradle dengan membuat class tugas kustom. Tambahkan class Anda ke project-root/buildSrc/src/main/groovy/ dan Gradle akan otomatis memasukkannya ke 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) tetapi 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 resource gambar. Namun, Anda mungkin akan melihat sedikit peningkatan penggunaan CPU perangkat saat melakukan dekompresi gambar WebP. Melalui Android Studio, Anda dapat mengonversi gambar ke WebP dengan mudah.

Menonaktifkan pemrosesan PNG

Jika Anda tidak dapat (atau tidak ingin) mengonversi gambar PNG ke WebP, Anda tetap dapat mempercepat proses build dengan menonaktifkan kompresi gambar otomatis setiap kali Anda membuat aplikasi. Jika Anda menggunakan plugin Android 3.0.0 atau yang lebih tinggi, pemrosesan PNG dinonaktifkan secara default hanya untuk jenis build "debug". Untuk menonaktifkan pengoptimalan ini untuk jenis build lainnya, tambahkan kode berikut ini ke file build.gradle Anda:

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

    // If you're using an older version of the plugin, use the
    // following:
    //  aaptOptions {
    //      cruncherEnabled false
    //  }
    }
    

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

Mengaktifkan cache build

Cache build menyimpan output tertentu yang dihasilkan oleh plugin Android untuk Gradle saat membuat project Anda (seperti AAR yang tidak dikemas dan dependensi remote pre-dexed). Clean build Anda akan jauh lebih cepat saat menggunakan cache karena sistem build cukup menggunakan kembali file-file yang telah di-cache tersebut selama proses build berikutnya, tanpa perlu membuatnya kembali.

Project baru yang menggunakan plugin Android 2.3.0 dan versi yang lebih tinggi mengaktifkan cache build secara default (kecuali jika Anda menonaktifkan cache build secara eksplisit). Untuk mempelajari lebih lanjut, baca Mempercepat clean build dengan cache build.

Menggunakan pemroses anotasi inkremental

Plugin Android Gradle 3.3.0 dan versi yang lebih tinggi meningkatkan dukungan untuk pemrosesan anotasi inkremental. Jadi, untuk meningkatkan kecepatan incremental build, Anda perlu mengupdate plugin Android Gradle dan hanya menggunakan pemroses anotasi inkremental jika memungkinkan.

Catatan: Fitur ini kompatibel dengan Gradle versi 4.10.1 dan yang lebih tinggi, kecuali untuk Gradle 5.1 (lihat Gradle edisi #8194).

Untuk memulai, lihat daftar pemroses anotasi populer berikut yang mendukung pemrosesan anotasi tambahan. Untuk daftar lebih lengkap, baca Status dukungan dalam pemroses anotasi populer. Beberapa pemroses anotasi mungkin memerlukan langkah tambahan untuk mengaktifkan pengoptimalan, jadi pastikan untuk membaca dokumentasi setiap pemroses anotasi.

Selain itu, jika menggunakan Kotlin di aplikasi, Anda harus menggunakan kapt 1.3.30 dan versi lebih tinggi untuk mendukung pemroses anotasi inkremental untuk kode Kotlin Anda. Pastikan untuk membaca dokumentasi resmi guna mengetahui apakah Anda perlu mengaktifkan perilaku ini secara manual atau tidak.

Perlu diingat, jika Anda harus menggunakan satu atau beberapa pemroses anotasi yang tidak mendukung incremental build, pemrosesan anotasi tidak akan bertambah. Namun, jika project Anda menggunakan kapt, kompilasi Java masih bersifat inkremental. Jika Anda tidak menggunakan kapt dan ingin kompilasi Java menjadi inkremental, pertimbangkan untuk menyertakan tanda berikut ini di file gradle.properties Anda. Jika itu yang Anda lakukan, plugin Android Gradle akan mengeksekusi semua pemroses anotasi dalam tugas terpisah dan memungkinkan tugas kompilasi Java berjalan secara inkremental.

    android.enableSeparateAnnotationProcessing = true
    

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 kendala. Anda dapat melakukannya dengan memprofilkan durasi waktu yang diperlukan Gradle untuk mengeksekusi setiap fase siklus 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 memindahkan logika build kustom keluar dari fase konfigurasi. Selain itu, jika tugas mergeDevDebugResources menghabiskan sejumlah besar waktu build, ini mungkin menandakan bahwa Anda perlu mengonversi gambar ke WebP atau menonaktifkan pemrosesan PNG.

Menggunakan profiling untuk meningkatkan kecepatan build biasanya melibatkan proses menjalankan build dengan profiling aktif, melakukan beberapa perubahan pada konfigurasi build, dan melakukan profiling lagi untuk mengamati hasil perubahan Anda.

Untuk membuat dan melihat profil build, lakukan langkah-langkah berikut:

  1. Saat project Anda terbuka di Android Studio, pilih View > Tool Windows > Terminal untuk membuka command line di tingkat root project.
  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 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 profiling.
    • --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 kembali 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 lalu 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 pada langkah 3, tetapi hilangkan tanda --rerun-tasks. Karena Gradle mencoba menghemat waktu dengan tidak mengeksekusi ulang tugas yang inputnya tidak berubah (ini dinyatakan dengan tanda UP-TO-DATE pada tab Task Execution dalam laporan, seperti yang ditunjukkan pada gambar 3), Anda bisa mengidentifikasi tugas apa saja yang melakukan pekerjaan padahal seharusnya tidak. Misalnya, jika :app:processDevUniversalDebugManifest tidak ditandai UP-TO-DATE, itu mungkin berarti bahwa konfigurasi build Anda memperbarui manifes secara dinamis untuk setiap build yang dirilis. Namun, beberapa tugas perlu dijalankan selama 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 memanfaatkan ProGuard untuk menghapus kode yang tidak terpakai dan mengecilkan ukuran APK. Namun, project yang lebih kecil mungkin akan lebih diuntungkan dengan menonaktifkan ProGuard sepenuhnya. Selain itu, peningkatan ukuran heap Gradle (menggunakan org.gradle.jvmargs) bisa 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.

Tips: Untuk fitur profiling yang lebih tangguh, pertimbangkan untuk menggunakan profiler open-source Gradle.