1. 程式人生 > >6個技巧加速你的gradle編譯

6個技巧加速你的gradle編譯

head 再次 spl ges 預編譯 src rtu cdn url

近期我們都在討論build系統,我們看了一些技巧能夠讓你的Maven build更快。

結論和反映都勢不可擋。由於我們提供的技巧,很多其它的人都非常高興能加快他們完畢自己的項目。如今,讓我們看一下怎麽處理gradle編譯項目。

編譯的項目一般都是標準編譯的,也都是獨一無二的。差點兒全部的項目都添加了其自身的復雜性。

全部的東西都不同可是有一個東西是相同的:編譯會占用你的時間,加快編譯會影響你的開發效率,讓你的項目工作更加順暢。

事不宜遲,讓我們來看看什麽是Gradle。和它的理念:
技術分享

加速Gradle編譯

這篇文章主要是由Madis Pink大力提倡的:Squeezing the Last Drop of Performance Out of Your Gradle Builds.Madis是JRebel的Androidproject師,所以假設你是一個搞Android的,我建議你應該試一下。Madis熱衷於這些,可是你不會觀察到有關他太多。

對於一個測試項目我們用Madis用過的代碼:一個Android項目demo iosched(http://github.com/google/iosched)。不要害怕。gradle對於Android項目和你的Java項目是一樣的。

這意味著我給你的建議相同適用於你其它的項目的環境。

所以你相同也能用這些技巧去加速你的JAVA項目編譯。

在開始優化之前,我們首先須要理解一下Gradle的生命周期。它被拆分為3個不同階段:

  1. 初始化:掃描項目,找出哪些內容須要被編譯
  2. 配置:運行build.gradle腳本,創建任務圖
  3. 運行:構建你APP實用的部分

如今你是不是頭痛了?確實有一個實用的階段。我們或許能夠在我們自己的編譯腳本加快,Gradle全然運行自私的任務:配置本身和實施運行開銷。

在這篇文章中。我們將首先集中精力降低構建的開銷之前,我們盡量使構建本身更快。

讓我們開始一步優化構建步驟,同一時候測量進度。假設你想自己運行 iosched,從GitHub得到它,就像這樣:

git clone http://github.com/google/iosched
cd ioshed

如今我們準備去克隆了!

讓我們用手中典型的開發環境用gradle去build這個APP來獲取依賴。


再次編譯我們的項目,可是用dry-run(能夠讓gradle去跳過全部任務的運行)。
這意味著,我們將運行配置gradle,並運行全部它一般會做的任務僅僅是沒有做實際工作。這正是我們須要測試而且降低開銷的。
運行以下命令幾次。由於你第一次做這種構建將拉低所需的依賴,假設你使用一個新的項目。運行以下的命令:

./gradlew :android:assembleDebug --dry-run

在考慮到全部的gradle運行的任務之後,跳過dry-run,會打印出運行這個命令會消耗多少時間。在我的2013年的MacBook Pros上仍然須要9s。

BUILD SUCCESSFUL
Total time: 8.674 secs

一個標準的測量時須要多次運行命令。然後去出平均測量結果。由於我們不是在做科學實驗,全部跳過這些鼓噪的步驟。帶著一粒鹽,你的裏程可能會發生變化(這句話我也沒懂什麽意思…)

第二步是在gradle構建時啟用分析。去看這些gradle命令你會獲取到一份好的日誌:

./gradlew :android:assembleDebug --dry-run --profile
 open build/reports/profile/profile-2016-02-02-15-39-17.html

這份日誌顯示,大部分的時間消耗在了配置項目上:
技術分享
所以讓配置更快一些。

1.使用配置需求

有一個降低時間的方法:我們須要盡早的讓gradle去配置。幸運的是,這僅僅是另外的一種加入命令標誌:

./gradlew :android:assembleDebug --dry-run --profile --configure-on-demand

非常明顯,結果好了一些,變成了7s:

BUILD SUCCESSFUL
Total time: 7.144 secs
這個日誌顯示了在我們調用了這個命令之後降低了2.359s。似乎能夠忽略不計。可是換句話來說你就會認為有意義了–這是一個17%的加速了。

配置這樣一個命令對gradle是一個孵化的功能,所以它不是默認啟用的。或許將來的一天能夠默認開啟,可是如今我們能夠全局使用它。通過在你的home文件夾下加一行.gradle/gradle.properties。
這個命令也滿足在linux和OSX系統下:

echo ‘org.gradle.configureondemand=true‘ >> ~/.gradle/gradle.properties

2.使用gradle daemon

如今,由於我們正在談論全局性,我們也能夠使用gradle daemon。gradle daemon是一個後臺進程。在gradle構建完畢之前不會退出。下次你能夠直接調用gradle,它仍然等待你下次調用。這有非常大意義,由於gradle是一個須要啟動的JVM進程。載入JVM。載入class,JIT等等。gradle daemon的作用就是限制全部的開銷。


讓我們比較一下使用gradle daemon和不適用gradle daemon所消耗的時間:

./gradlew :android:assembleDebug --dry-run --no-daemon
# vs. 
./gradlew :android:assembleDebug --dry-run --daemon

在我的機器上,一段時間後,使用gradle daemon要比不適用快的不是一點點:

BUILD SUCCESSFUL
Total time: 2.536 secs
如今僅僅用了2.536s。是不是非常爽?用gradle daemon確實非常棒。所以你應該把它設置成全局的。

echo ‘org.gradle.daemon=true‘ >> ~/.gradle/gradle.properties

3.用最新的gradle版本號

以下我們開始討論一下gradle的版本號問題。

gradle是一個比較復雜的‘怪物’,大多數的項目隨著每一個release版本號越來越快。所以用最新的版本號有非常大意義。
到如今為止最新的gradle版本號是2.2.1,最新的gradle release更新是2.10,。讓我們升級用最新的版本號。用不同的構建工具,升級的過程是非常痛苦的。gradle不一樣,大多數項目都用的gradle編譯,修復gradle版本號確保構建反復性。假設你的項目用gradle編譯確實非常棒,而且你也應該用wrapper。比如在他的 Virtual JUG session上面,Andres Almiray:JAVA大牛。也是一個gradle粉絲。

相信他,他對gradle的了解不是一點點。

當我們用wrapper的時候,去改變我們正在用的gradle版本號,僅僅須要去更改wrapper配置中的幾個數字而已。

這個配置文件在 項目根文件夾gradle/wrapper/gradle-wrapper.properties文件以下。
遺憾的是。由於配置上的一些bug,gradle非常easy失敗:

Failed to apply plugin [id ‘com.android.application’]
Gradle version 2.2 is required. Current version is 2.10. If using the gradle wrapper, try editing the distributionUrl in /Users/shelajev/repo/tmp/iosched/gradle/wrapper/gradle-wrapper.properties to gradle-2.2-all.zip

非常顯然。這是一個在比較gradle版本號的時候出現的問題。假設用gradle wrapper。試著去改成2.9.然後我們看一下2.9的編譯速度:

BUILD SUCCESSFUL
Total time: 1.356 secs
gradle 2.9 果真沒讓我們失望。從來沒這麽快過,由之前的8s編程如今的1.3s。

同理也使用與JAVA版本號。假設你還沒有升級到JAVA1.8,立即升級吧。

讀完這篇文章,立即行動吧。

你還沒實用JAVA 8的lambdas.
確保你的構建工具最新。那麽你會得到最高效的JAVA版本號運行。

4.優化項目

到如今為止。我們一直在談編譯消耗在構建上。說實話,大部分你能夠加速優化的地方在實際的構建過程中隱藏掉了。

好吧,在我們的demo中,我們保存的大部分時間在消除開銷。可是我們看看生成項目會發生什麽?讓我們看一下如何能真正的加速gradle構建。

5.避免繁重的計算

通常情況下,我們能夠避免大部分的gradle構建所做的繁重的工作。

讓我們看看demo,嘗試去降低gradle構建時的IO輸出。

比如。你如今構建一個典型的APP為了持續集成,你須要去保存你構建的的一些信息。

這些信息僅僅是一些命令?在你的gradle.build文件裏你能夠看到:

def cmd = ‘git rev-list HEAD --first-parent --count‘
def gitVersion = cmd.execute().text.trim().toInteger()
android {
  defaultConfig {
    versionCode gitVersion
  }
}

上面的代碼運行一個Git命令。並將結果以供以後使用變量。可是實際上,命令運行須要非常多時間。為了您的開發環境的目的。你可能並不須要這些信息。

幸運的是:gradle真的非常靈活。這些配置僅僅是純的Groovy文件。所以,假設你改變上面的配置。就像以下的樣例一樣:

def gitVersion() {
  if (!System.getenv(‘CI_BUILD‘)) {
    // don‘t care
    return 1
  }
  def cmd = ‘git rev-list HEAD --first-parent --count‘
  cmd.execute().text.trim().toInteger()
}
android {
  defaultConfig {
    versionCode gitVersion()
  }
}

非常輕松避免這種計算,所以你應該註意將上面的代碼保存下來。

6.修復依賴

gradle同意你指定項目中依賴包的範圍,在以下的樣例中。不論什麽一個gson 2的小版本號都滿足依賴約束。其實。gradle嘗試去找最新的版本號,這就消耗了gradle的靈活性。gradle不得不去網上查詢哪個版本號可用。這有的是不必要的,尤其假設你的網絡環境非常差,像這樣:

dependencies {
    compile ‘com.google.code.gson:gson:2.+‘
}

這樣不僅會減慢你的項目編譯。同一時候也會失去了反復性的構建。
在不論什麽的情況下,避免動態依賴和固定版本號號都是一個好方法。這樣做不難。僅僅須要找到gradle如今的版本號號而且指定這個數就OK了。

模塊化項目和並行化編譯

最後,這個並非特別重要,可是或許是最有影響力的,它能提高你的項目編譯速度而且使你的項目模塊快更好。首先。模塊化項目能夠並行編譯。我們談論了它如何加快Maven和gradle。並行編譯。這是還有一種孵化功能。您須要提供還有一個命令行標誌。你也能夠給你的gradle命令或者gradle.properties文件裏加一個全局的flag

echo ‘org.gradle.parallel=true‘ >> ~/.gradle/gradle.properties

除了明顯的加速,它也比多線程構建多了以下幾個優點:
1. 並行project的配置
2. 復用之前的項目
3. 項目得到及時檢查
4. 在項目編譯過程中使用了預編譯
最後兩點比較重要,它能夠及時的非常好的改變你的代碼。這意味著gradle能夠弄清楚而且能夠避免不必要的構建項目。這所做的工作是有史以來最快的工作。

結論

在Madis Pink的討論中我們看到了幾個好的建議。

以下是簡短幾點:

  • 啟用按需配置
  • 用gradle daemon
  • 及時更新新版本號
  • 避免做繁重的計算
  • 不要動態使用依賴
  • 並行編譯

當中的一些建議能夠降低gradle本身的配置,降低你的項目構建,以及其它相似避免動態依賴和並行的運行。這些將使你的項目構建節省非常多時間。更加讓我們開心的是,這些建議相同使用與JAVA項目的構建。


假設你有其它的方法來更快的構建gradle,我更加開心。

記得把那些建議發給我。我會盡我所能來開源這些好的知識。當然你也能夠從這篇文章延伸出自己的更好的方法。

[email protected],咱倆能夠聊聊。

轉自:
http://zeroturnaround.com/rebellabs/making-gradle-builds-faster/.

翻譯自:
https:[email protected]/6-tips-to-speed-up-your-gradle-build-3d98791d3df9#.2wvd1b2i3

6個技巧加速你的gradle編譯