納尼?我的Gradle build編譯只要1s

納尼?我的Gradle build編譯只需要1s!!!

爲了避免被Diss,先聲明瞭,本文不算原創,只是對幾篇Gradle編譯提速的文章進行了:
搬運整理細化和補漏,文尾已列出相關的參考文獻!先上個圖舒服下:

(PS:這是直接新建的項目通過各種折騰後編譯的時間,筆者公司的項目折騰完耗時5s左右,
但是因爲兼容要改的東西多,升級gradle等操作並沒弄,不過也是效果明顯,真的可以試試~)

大部分的Android開發仔吐槽的最多的基本都是等Gradle編譯。

編譯可以說是日常操作最頻繁的,在調UI,調試改Bug時候達到一個峯值,每改點東西,
就build一下。可以說是相當可怕,我們來粗略的算一筆賬:

假設編譯一次要3分鐘,一天編譯40次

  • 每天花費:2小時等待編譯
  • 一週花費:14小時等待編譯
  • 一個月花費:60小時等待編譯 => 2.5天

每個月花2.5天是在等待Gradle編譯,多呆哦,所以,讓Gradle編譯提速,顯得格外重要,
本節就從方方面面說下減少這個等待的時間吧。


1.升級下你的電腦配置

大部分的Gradle編譯卡和慢,都是因爲電腦配置的原因,個人感覺關鍵基本配置如下:

  • CPU:i5系列就夠了
  • 內存:重要!至少要8G,有條件建議上16G
  • 硬盤:重要!必須是SSD固態硬盤,窮一點的上128G,稍微寬裕點上256

其他比如顯卡啊啥的沒什麼太大影響,配置肯定是越高越好,在自己的經濟承受範圍以內即可。


2.調整AS的內存分配

電腦配置差不多了,接下來就要調整下AS的可使用內存,打開AS在右下角可以看到使用內存和分配內存,如圖所示:

如果你的AS裏沒有這個圖的話,可以依次點擊菜單欄的:「File」->「Settings」->「Appearance % Behavior」->
Appearance」-> 找到如圖所示的「Show memory indicator」勾選,然後點擊OK,就可以在狀態欄看到內存分配信息了。

接着我們來修改AS的內存分配,來到AS的安裝目錄下,進入bin目錄,找到:

用文本編輯類軟件打開對應文件,內容如下:

-Xms256m
-Xmx1280m
-XX:ReservedCodeCacheSize=240m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-Djna.nosys=true
-Djna.boot.library.path=

-da

接着我們修改下前三項,改成更大的值:

-Xms512m    //JVM啓動的起始堆內存,堆內存是分配給對象的內存
-Xmx2560m   //Java虛擬機啓動時的參數,用於限制最大堆內存
-XX:ReservedCodeCacheSize=480m  //JIT java compiler在compile的時候的最大代碼緩存
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-Djna.nosys=true
-Djna.boot.library.path=

修改完後保存,然後回到AS中,依次點擊菜單欄:「File」->「Ivalidate Caches/Restart…」,點擊後出現如圖對話框,點擊「Ivalidate Caches/Restart…」。

然後等待AS重啓即可。然後右下角可以看到可用內存已經發生了改變,AS明顯打開流暢多了。


3.增加Gradle的堆大小並啓用dex-in-process

Dex-in-process允許你dex和gradle構建在同一個進程進行,以此加快增量構建和乾淨構建的速度。
要使用dex-in-process非常簡單:確保 grale 進程有足夠的內存分配給 dex 步驟來完成整個操作
建議的公式:

Gradle memory >= Dex memory + 1Gb !

就是分配給gradle的內存比dex的內存多1g,dex進程內存設置在開發module的 build.gradle裏面控制。添加如下內容:

除此之外,dexOptions中還可以添加下述配置:

//使用增量模式構建 
incremental true 

//是否支持大工程模式 
jumboMode = true 

//預編譯 
preDexLibraries = true 

//線程數 
threadCount = 8 

配置完dex,接着要配置gradle,打開「gradle.properties」修改org.gradle.jvmargs 的大小,按照公式,多1g,所以這裏配置成2g:

org.gradle.jvmargs=-Xmx2g

除此之外設置下JVM最大允許分配的非堆內存,以及堆內存移除時輸出堆的內存快照。

org.gradle.jvmargs=-Xmx2g -XX:MaxPermSize=0.5g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

接着可以再Terminal中中鍵入gradlew clean build來看看構建的速度是否加快了。
一般dex設置爲1-2G,gradle設置爲2-4G就可以了,分配更多的內存並不會使構建加快多少!


4.其他gradle.properties配置

除了配置給gradle分配的內存外,還可以通過添加下述配置使得構建加快:

#開啓守護線程
org.gradle.daemon=true
    
#開啓並行編譯任務
org.gradle.parallel=true
    
#開啓緩存
android.enableBuildCache=true

另外,你還可以在下述目錄中創建一個gradle.properties文件,全局生效,就不用每個項目都另外配置了,
當然你喜歡還是可以在項目中創建這個文件。


5.配置依賴包下載地址

就是使用阿國內阿里雲的依賴下載地址替換Google依賴包下載地址,打開Project級別的build.gradle文件,添加阿里雲的地址:

repositories {
    maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
    maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' }
    ...
}

allprojects {
    repositories {
        maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
        maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' }
        ...
    }
}    

6.離線編譯

如果你的項目比較穩定,沒有什麼新的依賴(第三方庫引用),可以使用這種方法來提升編譯速度。
依次點擊菜單欄「Setting」->「Build」-> 「Gradle」,找到如圖的「Offline work」勾選,點擊OK即可。

也可以不配置,在命令行編譯的時候加上**--offline**,比如:

gradlew build --offline

7.使用靜態依賴項版本

在引用依賴庫的時候,儘量避免使用+這種動態版本號,而儘量使用靜態編碼編碼版本號,
如果用動態版本號,每次編譯的時候Gradle會去檢查是否有更新,比如:

# 動態版本號
com.android.tools.build:gradle:3.2.+

# 靜態版本號
com.android.tools.build:gradle:3.2.1

8.禁用耗時但在Debug時不需要的Task

你可以通過下述兩種方式,查看編譯的時候都執行了哪些Task,以及他們的耗時。

方法一:通過gradlew --profile

編譯命令後加上–profile,比如 gradlew build --profile,會輸出打包過程的profile report

接着按照給出的路徑找到對應的html文件,用瀏覽器打開,點擊「Task Execution

然後就可以看到所有執行的Task和所需的耗時。除此之外,還可以

方法二:使用build scan(構建審視)

Gradle 官方推出的一個可視化診斷工具,官網地址:https://gradle.com/build-scans/,不同的Gradle版本對應的
build-scan-plugin的版本也不同,可以在官網查看對應的版本號:Gradle Enterprise version compatibility
比如我的4.6對應最低版本的build scan工具的版本號爲:1.8。接着在項目級別的build.gradle文件中添加相關代碼:

buildscript {
  repositories {
    maven {
      url "https://plugins.gradle.org/m2/"
    }
  }
  dependencies {
    classpath "com.gradle:build-scan-plugin:1.8"
  }
}

apply plugin: "com.gradle.build-scan"

接着命令鍵入:gradlew build --scan編譯完會問你是否Push到gradle.com,鍵入:
yes即可。

如果不想每次都鍵入yes,在build.gradle中添加下述代碼:

buildScan {                     
    licenseAgreementUrl = 'https://gradle.com/terms-of-service'
    licenseAgree = 'yes'
}

接着點擊打開鏈接,會讓你輸入一個接收報告的郵箱:

接着會受到一個郵件,點開就能看到本次編譯的相關信息了,比如這裏看到佔較多編譯時間的Task是lint:

行吧,從上面的兩個例子我們可以明顯的看到lint耗時不少,而Lint在Debug階段並不需要,我們可以下述三種方式來禁用:

  • 1.通過Grale編譯參數禁用
gradlew build -x lint -x lintVitalRelease
  • 2.Gradle腳本中動態添加編譯參數

項目級別的build.gradle中buildScript添加下述代碼:

gradle.startParameter.excludedTaskNames.add('lint')
gradle.startParameter.excludedTaskNames.add('lintVitalRelease')
  • 3.永久禁用lint

在模塊級別的build.gradle中的

apply plugin: 'com.android.application'

前加上下述代碼:

tasks.whenTaskAdded { task ->
    if (task.name.contains("lint") || task.name.contains("lintVitalRelease")) {
        task.enabled = false
    }
}

9.一些其他的小點

① 減少本地庫依賴

Gradle在編譯時會執行大量Task,生成很多中間文件,會導致磁盤IO擁堵,造成編譯變慢,
可以減少本地庫依賴,多使用aar進行依賴。

② 修改minSdkVersion>=21

如果你不需要兼容低版本的設備的話,可以把minSdkVersion改爲21以上(Android 5.0),使用ART,在Build時只做class to dex,
而不做mergeing dex,同樣會節省一點的時間。

③ 使用implementation替代compile

注:Gradle版本需大於3.4,示例如下:

compile 'com.android.support:appcompat-v7:28.0.0'
# 改爲:
implementation 'com.android.support:appcompat-v7:28.0.0'

同樣的替換還有:

  • testCompile -> testImplementation
  • androidTestCompile -> androidTestImplementation
  • provided -> compileOnly

④ 將圖像轉換成 WebP

有效減少圖片文件大小,不必執行構建時壓縮,從而加快構建速度,如果你的APP用到大量圖片資源的話,效果明顯。

⑤ 停用 PNG 處理

如果不想把圖片替換成WebP,可在每次構建應用時停用自動圖像壓縮的方式加快構建速度。模塊級別build.gradle添加下述代碼:

android {
  ...
  aaptOptions {
    cruncherEnabled false
  }
}

⑥ 按需編譯而不是無腦build

直接**gradlew build和執行gradlew assemble** 會同時編譯生成Debug和Release的包,在調試階段其實
我們可以使用:

gradlew assembleDebug

來只編譯Debug版本的包,除此之外還可以用另一個命令編譯完直接安裝到設備上:

gradlew installDebug

同理對應Release的命令爲:

gradlew assembleRelease
gradlew installRelease

行吧,關於Gradle編譯提速大概就這些,有補充的歡迎在評論區留言,謝謝~


參考文獻


Join in

歡迎大家加入開發交流羣一起討論學習,可以添加下述的機器人小號 RobotPig,發送『菜單
輸入對應的提示,加入對應的開發羣(Android或Python),或者在公衆號『摳腚男孩』中發送加羣~

半自動拉人,會有延時,請諒解~

機器人小號     


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章