作為 Android 開(kāi)發(fā)者工具團(tuán)隊(duì)的成員延届,我和團(tuán)隊(duì)成員們每天都抱著將 Android 打造成最好的移動(dòng)開(kāi)發(fā)者平臺(tái)的想法來(lái)制作各種工具。這意味著我們會(huì)構(gòu)建一些幫助您開(kāi)發(fā)應(yīng)用的工具,讓您專(zhuān)注于編寫(xiě)應(yīng)用续滋。
我們知道超長(zhǎng)的構(gòu)建既浪費(fèi)時(shí)間也會(huì)打斷開(kāi)發(fā)流程悯恍,并且會(huì)讓開(kāi)發(fā)者十分沮喪薄翅。Android Studio 用戶平均每周構(gòu)建 65 次微峰,所以即便每次構(gòu)建只慢 10 秒鐘也會(huì)浪費(fèi)每個(gè)開(kāi)發(fā)者一年大約 9 個(gè)小時(shí)的時(shí)間舷丹。盡管如此,如我們?cè)谏栽绲奈恼隆?a target="_blank">在 Android Studio 中優(yōu)化構(gòu)建速度》提到的县忌,大約有 60% 的 Android 開(kāi)發(fā)者不會(huì)去做構(gòu)建分析掂榔。再加上不斷增長(zhǎng)的項(xiàng)目復(fù)雜度继效,最終導(dǎo)致了所有使用 Android Studio 的項(xiàng)目構(gòu)建時(shí)間不斷增長(zhǎng)症杏,也嚴(yán)重影響了開(kāi)發(fā)效率。
為了解決這個(gè)問(wèn)題瑞信,我們制作了構(gòu)建分析器厉颤。這個(gè)工具可以幫助所有開(kāi)發(fā)者理解影響他們項(xiàng)目構(gòu)建時(shí)間的因素,以及如何減少這些因素的影響凡简。
充分使用構(gòu)建分析器 (Build Analyzer) 提供的功能
每次構(gòu)建應(yīng)用逼友,Android Studio 都會(huì)生成一個(gè)構(gòu)建分析器報(bào)告。為了看到這個(gè)報(bào)告秤涩,請(qǐng)確保您按照如下步驟操作:
- 升級(jí) Android Gradle Plugin 到 4.0.0 或更高版本帜乞。
- 構(gòu)建或者重新構(gòu)建您的工程。
- 通過(guò)選擇 View > Tool Windows > Build 菜單來(lái)訪問(wèn)構(gòu)建分析器筐眷,然后點(diǎn)擊 Build Analyzer 標(biāo)簽黎烈。
Santa Tracker 應(yīng)用是 Google 開(kāi)發(fā)的一個(gè)教程性質(zhì)的開(kāi)源應(yīng)用,為了這篇文章匀谣,我們將 clean build 這個(gè)應(yīng)用照棋,并和大家一起理解生成的構(gòu)建分析報(bào)告。
打開(kāi)構(gòu)建分析器武翎,您會(huì)看到 Overview 頁(yè)面烈炭。這個(gè)頁(yè)面展示了一些基本信息以及跳轉(zhuǎn)到各個(gè)詳情頁(yè)的鏈接。如下圖所示宝恶,我們立即就會(huì)發(fā)現(xiàn)符隙,這個(gè)構(gòu)建的耗時(shí)主要來(lái)自于任務(wù)執(zhí)行而不是構(gòu)建的配置趴捅。
為了了解更多,讓我們來(lái)繼續(xù)深入分析構(gòu)建分析器所提供的兩個(gè)數(shù)據(jù)集膏执。它們分別是 Tasks (任務(wù)) 和 Warnings (警告)驻售。您既可以通過(guò) Common views into this build 下的鏈接來(lái)訪問(wèn),也可以通過(guò)左上角當(dāng)前顯示 "Overview" 的下拉菜單來(lái)切換更米。
任務(wù)
這些任務(wù)決定了剛剛觀察到的構(gòu)建時(shí)間欺栗,其中有的是因?yàn)檩斎搿⑤敵龅囊蕾?lài)關(guān)系征峦,而其他的則是由于并行構(gòu)建的約束迟几。除此之外的任務(wù),可以并行運(yùn)行并且不會(huì)對(duì)構(gòu)建時(shí)間有影響栏笆。查看這個(gè)面板可以告訴我們構(gòu)建應(yīng)用的哪個(gè)步驟是最耗時(shí)的类腮。
當(dāng)展開(kāi)列表來(lái)查看這些任務(wù)的時(shí)候,每個(gè)任務(wù)會(huì)根據(jù)來(lái)源顯示為不同的顏色蛉加。來(lái)自 Project Customizations 的任務(wù)是由您項(xiàng)目的本地自定義的蚜枢,也是最容易被修改的。被標(biāo)示為 Android/Java/Kotlin Plugins 的任務(wù)來(lái)自于核心插件针饥。而 Other Binary Plugins 的任務(wù)要么是來(lái)自您團(tuán)隊(duì)成員編寫(xiě)的二進(jìn)制插件厂抽,或者是來(lái)自第三方制作的二進(jìn)制插件。
默認(rèn)情況下這些任務(wù)會(huì)以展開(kāi)列表的形式顯示丁眼,但是也可以使用 Group by plugin 選項(xiàng)來(lái)按照任務(wù)來(lái)源的插件分組筷凤。這樣分組會(huì)將您項(xiàng)目中的每個(gè)插件顯示為一個(gè)節(jié)點(diǎn),而不是按照單個(gè)任務(wù)來(lái)顯示苞七。
這樣分組會(huì)讓我可以觀察到藐守,我項(xiàng)目構(gòu)建的大部分時(shí)間是在執(zhí)行來(lái)自核心插件的任務(wù),比如 Kotlin 或者 Android Gradle 的插件蹂风。這并不意外卢厂,尤其是在對(duì)于像 Santa Tracker 一樣的項(xiàng)目運(yùn)行全量構(gòu)建的時(shí)候。而在運(yùn)行增量構(gòu)建的時(shí)候惠啄,核心插件的任務(wù)通常會(huì)耗費(fèi)相對(duì)較少的時(shí)間慎恒,這樣會(huì)便于我們發(fā)現(xiàn)其他插件對(duì)于構(gòu)建時(shí)間的影響。
當(dāng)我們需要比較添加或者升級(jí)某個(gè)插件對(duì)于構(gòu)建時(shí)間影響的時(shí)候礁阁,這個(gè)插件視圖格外有用巧号,因?yàn)樗鼤?huì)幫助您權(quán)衡更改的好處和它們對(duì)于構(gòu)建時(shí)間帶來(lái)的影響。無(wú)論什么時(shí)候姥闭,對(duì)于更改的謹(jǐn)慎是防止我們不斷地增加項(xiàng)目構(gòu)建時(shí)間的最好辦法丹鸿,也就能避免其影響我們的開(kāi)發(fā)效率。
警告
這個(gè)視圖可以讓您看到該構(gòu)建生成的所有警告棚品,其中也包括了那些并不會(huì)影響構(gòu)建時(shí)間任務(wù)的警告靠欢。
每個(gè)警告信息都會(huì)包含其產(chǎn)生的原因和推薦的解決辦法廊敌,以及如果適用的話,也會(huì)包含生成該警告的任務(wù)的詳細(xì)信息门怪。如果該警告不是來(lái)自您的團(tuán)隊(duì)成員的插件骡澈,您可以使用 Generate report功能來(lái)向該任務(wù)或插件的作者進(jìn)行反饋。
如上圖顯示掷空,在使用構(gòu)建分析器分析我們之前提到的 Santa Tracker 項(xiàng)目時(shí)肋殴,生成了一個(gè) Task Setup 警告。這個(gè)問(wèn)題看起來(lái)是由于輸出目錄沖突造成的坦弟,所以我們可以修改 generateExtraResources 任務(wù)和 mergeDebugResources 任務(wù)其中之一的輸出文件路徑护锤。mergeDebugResources 任務(wù)來(lái)自于 android 基礎(chǔ)插件,并且不能在本地修改酿傍。generateExtraResources 任務(wù)被標(biāo)示為 project customization 且該任務(wù)是我的團(tuán)隊(duì)制作的烙懦。基于此我決定修改 generateExtraResources 任務(wù)赤炒。
另外需要注意的是氯析,上面的報(bào)告來(lái)自于全量構(gòu)建,而增量構(gòu)建的報(bào)告之間會(huì)不太一致莺褒,但卻可能更真實(shí)地反映您平時(shí)的開(kāi)發(fā)流程掩缓。所以在使用構(gòu)建分析器的時(shí)候,請(qǐng)確保您使用了全量構(gòu)建和增量構(gòu)建癣朗。想要了解更多關(guān)于構(gòu)建分析器的內(nèi)容拾因,請(qǐng)查閱 Android 開(kāi)發(fā)者官方文檔|排查構(gòu)建性能問(wèn)題旺罢。
構(gòu)建分析器如何工作
每當(dāng)您使用 Android Studio 構(gòu)建您的項(xiàng)目旷余,構(gòu)建分析器會(huì)使用 Gradle Tooling API 和 Android Gradle Plugin 在本地收集數(shù)據(jù)。Tooling API 會(huì)被用來(lái)綁定 ProgressListener扁达,它會(huì)提供關(guān)于項(xiàng)目的配置正卧、任務(wù)執(zhí)行、注解處理器等信息跪解。Android Gradle 插件會(huì)提供更多的其他信息炉旷,包括任務(wù)名稱(chēng)和任務(wù)類(lèi)名的映射,以及任務(wù)的配置信息叉讥。
當(dāng)您的構(gòu)建結(jié)束的時(shí)候窘行,構(gòu)建分析器會(huì)將這些信息輸入一系列的分析器,每個(gè)分析器會(huì)找到并報(bào)告特定的問(wèn)題图仓。舉個(gè)例子罐盔,有一個(gè)分析器會(huì)檢查那些被設(shè)置為每次構(gòu)建都需要執(zhí)行的任務(wù),因?yàn)檫@些任務(wù)會(huì)阻礙增量構(gòu)建節(jié)省時(shí)間救崔,而這會(huì)嚴(yán)重影響構(gòu)建速度惶看。
那這個(gè)分析器是如何發(fā)現(xiàn)那些每次都執(zhí)行的任務(wù)呢捏顺?當(dāng)一個(gè) Gradle 任務(wù)的輸入或輸出對(duì)比上一次構(gòu)建沒(méi)有變化的時(shí)候,這個(gè)任務(wù)被認(rèn)為是 up-to-date 的纬黎。當(dāng)一個(gè)任務(wù)是 up-to-date幅骄,Gradle 會(huì)跳過(guò)執(zhí)行該任務(wù)并復(fù)用這個(gè)任務(wù)以前的輸出口柳,而不是浪費(fèi)時(shí)間重新執(zhí)行它司致。如果一個(gè)任務(wù)沒(méi)有聲明輸入或輸出贡耽,那它永遠(yuǎn)不會(huì)認(rèn)定為 up-to-date如蚜。這個(gè)分析器依靠 Gradle Tooling API 提供的任務(wù)輸出信息找到所有有問(wèn)題的任務(wù)艇劫,它們要么是沒(méi)有聲明任何輸出膝迎,要么是替換 up-to-date 為 false析恢。通過(guò)這個(gè)方法液样,這個(gè)分析器可以找到所有永遠(yuǎn)不會(huì) up-to-date 的任務(wù)铐达,而這些任務(wù)每一次構(gòu)建都會(huì)運(yùn)行岖赋。我們希望可以利用這個(gè)分析器幫助您快速地定位問(wèn)題,并開(kāi)始充分利用增量構(gòu)建瓮孙。
目前除了這個(gè)可以識(shí)別每次構(gòu)建都運(yùn)行的任務(wù)的分析器唐断,還有其他兩個(gè)分析器。其中一個(gè)可以識(shí)別 非增量的注解處理器杭抠,另外一個(gè)可以識(shí)別任務(wù)之間替換彼此的輸出脸甘。未來(lái)我們計(jì)劃繼續(xù)發(fā)布各種分析器,來(lái)幫助您快速地發(fā)現(xiàn)常見(jiàn)問(wèn)題以及掌握關(guān)于使用 Gradle 的最佳實(shí)踐偏灿。
后續(xù)行動(dòng)
如果構(gòu)建分析器報(bào)告了一個(gè)來(lái)自第三方插件任務(wù)的警告丹诀,您可以考慮向插件的原作者提交 bug 報(bào)告。類(lèi)似的問(wèn)題有可能不會(huì)被立即解決翁垂,但是這會(huì)幫助整個(gè)生態(tài)變得更好铆遭。如果您認(rèn)為這個(gè)問(wèn)題來(lái)自構(gòu)建分析器本身,請(qǐng)通過(guò)我們的 issue tracker 來(lái)讓我們知道沿猜。
如果您有興趣深入理解您的項(xiàng)目構(gòu)建枚荣,請(qǐng)嘗試用 Gradle Scan 來(lái)獲取更多額外的信息。此外啼肩,使用 Gradle 的 Build Cache 也可能減少您的構(gòu)建時(shí)間橄妆。
隨著這個(gè)工具逐漸成熟,我們希望能夠擴(kuò)展分析器套件來(lái)識(shí)別更多的警告祈坠。我們熱切地希望了解人們是如何使用這個(gè)工具害碾,同時(shí)我們也會(huì)繼續(xù)改進(jìn)跳轉(zhuǎn)瀏覽、圖形化和其他相關(guān)組件赦拘。如果您有任何反饋慌随,尤其是那些您在自己的項(xiàng)目構(gòu)建中發(fā)現(xiàn)的,但是沒(méi)有被我們的分析器捕獲到的問(wèn)題另绩,請(qǐng)告知我們儒陨。