Android Gradle 構建優化

Android Gradle 構建優化

背景

本地構建的時候一次須要比較長的時間,存在優化空間。可使用 --profile 參數來分析構建過程當中各個任務的耗時狀況,好比 ./gradlew assembleDebug --profilehtml

本文基於的硬件條件:java

  • MacBook Pro 2017
  • 8G + 256G

現狀

./gradlew assembleDebug --profileandroid

增量編譯:緩存

首次編譯(無緩存):微信

開發時構建優化

開發時的 Gradle 構建優化比較有意義,構建測試包、正式包的時候並不須要那麼關注構建時間。能夠將開發時的構建與提測構建分離,新建一個本地開發用的 productFlavor - local,本地開發時只構建 local 包,在本地開發構建過程當中禁用掉沒必要要的任務(好比 lint, multidex, optimization 等),減小構建時間。jvm

優化開發構建中的 Dalvik 可執行文件分包

https://developer.android.com/studio/build/multidex#multidexkeepproguardide

新建一個 local 的 productFlavor,設置 minSdkVersion 爲 21,這樣就會啓用 pre-dexing 構建功能(僅適用於 Android 5.0+),可以加快打包速度,改動以下:工具

禁用構建時對 /res/drawable 目錄下圖片的優化

Android 構建工具默認會對 drawable 下的圖片進行優化,好比圖片壓縮轉換,校驗等,這個過程是比較耗時的,尤爲是當圖片比較多的時候。改動以下:post

dexOptions 配置優化

android.dexOptions 的配置優化測試

一些比較老的文章還會推薦 dexOptions.incremental,這是不必的,在 Gradle 2.1.0-rc1 (2016-04-22) 以後,incremental 增量構建已經默認啓用了,再也不須要顯式聲明。 此外,dexOptions.jumboMode 參數也是可選的,在啓用 instant-run 時這個參數會默認啓用

使用 Gradle 依賴緩存

Gradle 在構建時都會去拉依賴,順序是:本地緩存 -> 遠程依賴。若是使用了動態版本,那麼每次 Gradle 都會拉最新的依賴,在依賴多的狀況下是很是耗時的,從下面這張圖能夠看出(挖財寶):

從上圖中能夠看出,光是拉依賴就用了 3 分鐘,這都還沒到編譯階段,難怪打個包要六七八分鐘。。。

在 Gradle 中,最好固定依賴的版本號,這樣就不會每次編譯都從新拉依賴,可是在目前快速迭代的背景下,通常都是鎖死第一位,第二位和第三位版本號自動更新,也無法鎖死依賴,只能把以前 resolutionStrategy 改一下,使用 Gradle 默認的動態版本號緩存策略(Gradle 的動態版本也會有緩存滴),改動以下:

改動以後的效果分析以下,拉依賴的時間從 3min 變成了 20s 左右,效果明顯。

可是這種狀況下,若是 snapshot 版本的依賴更新了,可能不會及時自動更新到本地(由於緩存),不過 Gradle 支持 --refresh-dependencies 參數,使用 ./gradlew assembleLocalDebug --refresh-dependencies 會全量刷新依賴。

gradle.properties 中的一系列優化參數(可選)

org.gradle.daemon = true

The Gradle Daemon

Gradle 是基於 JVM 的構建系統,JVM 的啓動和初始化須要時間,開啓 Gradle Daemon 守護進程能夠節省這些時間

org.gradle.configureondemand = true

一次 Gradle 編譯大概由這幾部分組成:初始化、加載 setting.gradle(|| setting.gradle.kts)、加載各個模塊的 build.gradle(|| build.gradle.kts)、執行一系列任務。從上圖中能夠看到,Configuring Projects 也是花了 5s 左右的時間,使用 org.gradle.configureondemand=true 能夠加速這一過程。

org.gradle.parallel = true

啓用 Gradle 並行編譯,加速編譯過程

org.gradle.jvmargs = -Xmx2560M

設置 Gradle 編譯時使用的最大內存,大一點比較好,可是個人小本本內存只有 8G,有心無力。。。 使用大內存時 Android 編譯過程當中的 dexing 就不會單獨開進程進行,能節省構建時間。

android.enableBuildCache = true

啓用 Android 編譯構建緩存,此舉能極大提高構建效率,推薦! 可是我司由於統跳編譯插件不支持編譯緩存,所以只能禁用。

綜上所述

綜上所述,挖財寶中啓用的開發時構建優化措施有:

  • 設置 minSdkVersion 爲 21
  • /res/drawable 目錄下圖片的優化
  • dexOptions 配置優化
    • jumboMode = true
    • javaMaxHeapSize = "2g"
    • preDexLibraries = true
    • threadCount = 8
  • gradle.properties 配置優化
    • org.gradle.daemon = true
    • org.gradle.configureondemand = true
    • org.gradle.parallel = true
    • org.gradle.jvmargs = -Xmx2560M,大內存的話能夠再大一點
    • android.enableBuildCache = true 用不了。

優化後使用 ./gradlew assembleLocalDebug 生成開發包,或者使用 ./gradlew installLocalDebug 直接安裝。 提測時使用 offcialDebug 或者 qqDebug 都可。打生產包時使用 offcialRelease 或者 qqRelease

優化以後的效果以下圖所示,增量編譯通常能夠控制在 2min 之內

增量編譯:

首次編譯(無緩存):

題外話

  1. 其實,提高 Gradle 構建速度的最有效途徑不在上面,很簡單,換個 Mac Pro 來編譯就行了
  2. 上文中提到的幾個 gradle.properties 中的配置,若是隻想本地使用,就不要寫在 gradle.properties 中,能夠寫在 local.properties 或 ~/.gradle/gradle.properties 中
  3. 若是條件容許的話,使用最新的 Gradle 版本吧,新版的 Gradle 構建速度絕對比舊版本的快(目前是 Gradle 5.0)
  4. 移除沒必要要的三方依賴
  5. 按需編譯,部分 task 在開發的時候是不須要執行的,好比 lint,直接禁用掉便可,可使用 --profile 參數進行分析,分析報告在 build/reports/profile/ 目錄下
  6. 優化永無止境

參考資料

  1. 納尼?個人Gradle build編譯只要1s
  2. 6個技巧加速你的gradle編譯
  3. Gradle Docs - The Gradle Daemon

Personal

  • 微信公衆號:yongf666
  • 掘金:https://juejin.im/user/57b8751a2e958a005fa2fc45
  • 我的網站:https://www.54yongf.com/
  • 微博:http://weibo.com/2902237231
  • 知乎:http://www.zhihu.com/people/wang-yong-8-33
  • 郵箱:ScottWang1996@gmail.com
  • StackOverflow:http://stackoverflow.com/users/5304207
相關文章
相關標籤/搜索