<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
Android系統模組程式碼的編譯實在是太耗時了,即使寥寥幾行程式碼的修改,也能讓一臺具有足夠效能的編譯伺服器工作十幾分鍾以上(模組單編),只為編出一些幾兆大小的jar和dex。
這裡探究的是系統完成過一次整編後進行的模組單編,即m、mm、mmm等命令。
除此之外,一些不會更新原始碼、編譯設定等檔案的內容的操作,如touch、git操作等,會被Android系統編譯工具識別為有差異,從而在編譯時重新生成編譯設定,重新編譯並沒有更新的原始碼、重新生成沒有差異的中間檔案等一系列嚴重耗時操作。
本文介紹關於編譯過程中的幾個階段,以及這些階段的耗時點/耗時原因,並最後給出一個覆蓋一定應用場景的基於ninja的加快編譯的方法(實際上是裁剪掉冗餘的編譯工作)。
編譯伺服器硬體及Android資訊:
之所以做一個程式碼修改量微乎其微的case,是因為要分析編譯效能瓶頸,程式碼變更量越小的情況下,瓶頸就越明顯,越有利於分析。
由於Makefile
結構複雜、不易偵錯、難以擴充套件,因此Android決定將它替換掉。Android在7.0時引入了Soong
,它將Android從Makefile
的編譯架構帶入到了ninja
的時代。
Soong
包含兩大模組,其中Kati
負責解析Makefile
並轉換為.ninja
,第二個模組Ninja
則基於生成的.ninja
完成編譯。
Kati
是對GNU Make
的clone,並將編譯後端實現切換到ninja。Kati
本身不進行編譯,僅生成.ninja
檔案提供給Ninja
進行編譯。
Makefile/Android.mk -> Kati -> Ninja Android.bp -> Blueprint -> Soong -> Ninja
因此在執行編譯之前(即Ninja
真正開動時),還有一些生成.ninja
的步驟。關鍵編譯階段如下:
Soong的自舉(Bootstrap),將Soong本身編譯出來
系統程式碼首次編譯會比較耗時,其中一個原因是Soong要全新編譯它自己
遍歷原始碼樹,收集所有編譯組態檔(Makefile/Android.mk/Android.bp)
驗證編譯組態檔的合法性、有效性、時效性、是否應該加入編譯,生成.ninja
最後一步,真正執行編譯,呼叫ninja進入多執行緒編譯
下面將基於模組單編(因開發環境系統全新編譯場景頻率較低,不予考慮),對這四個關鍵階段進行效能分析。
在系統已經整編過一次的情況下,Soong已經完成了編譯,因此其預熱過程佔整個編譯時間的比例會比較小。
在“環境”下,修改一行Framework程式碼觸發差異進行編譯。並且使用下面的命令進行編譯。
time m services framework -j57
編譯實際耗時22m37s:
build completed successfully (22:37 (mm:ss)) ####
real 22m37.504s
user 110m25.656s
sys 12m28.056s
對應的分階段耗時如下圖。
0.8%
。注:這個耗時是僅小幅度修改Java程式碼後測試的耗時。如果修改編譯組態檔如Android.mk,會有更大的耗時。
小結:看來在完成一次整編後的模組單編,包括Soong bootstrap、執行編譯準備指令碼、vendorsetup指令碼的耗時佔比很低,可以完全排除存在效能瓶頸的可能。
從上圖可以看到,Kati
耗時佔比很大,它的任務是遍歷原始碼樹,收集所有的編譯組態檔,經過驗證和篩選後,將它們解析並轉化為.ninja
。
從效能角度來看,它的主要特點如下:
直觀展示如下,它是一個單執行緒的、IO速度敏感、CPU不敏感的過程:
Kati序列地處理檔案,此時對CPU利用率很低,對IO的壓力也不高。
小結:可以確定它的效能瓶頸來源於IO速度,單純為編譯範例分配更多的CPU資源也無益於提升Kati的速度。
Soong
Clone了一份GNU Make
,並將其改造為Kati
。即使我們沒有修改任何mk檔案,前面Kati
仍然會花費數分鐘到數十分鐘的工作耗時,只為了生成一份能夠被Ninja
或.ninja
的生成工具能夠識別的檔案。接下來是呼叫Ninja
真正開始編譯工作。
從效能角度來看,它的主要特點如下:
.ninja
檔案中能找到target和build rule就能完成編譯直觀展示如下,Ninja
將會根據傳入的並行任務數引數啟動對應數量的執行緒進行編譯。Ninja
編譯階段會真正的啟動多執行緒。但做不到一直多執行緒編譯,因為部分階段如部分編譯目標(比如生成一個API檔案)、泛打包階段等本身無法多執行緒並行執行。
可以看到此時CPU利用率應該是可以明顯上升的。但是耗時較大的階段僅啟用了幾個執行緒,後面的階段和最後的圖形很細(時間佔比很小)的階段才用起來更多的執行緒。
其中,一些階段(圖中時間佔比較長的幾條記錄)沒能跑滿資源的原因是這些編譯目標本身不支援並行,且本次編譯命令指定的目標已經全部“安排”了,不需要調動更多資源啟動其他編譯目標的工作。當編譯整個系統時就能夠跑滿了。
最後一個階段(圖中最後的幾列很細的記錄)雖然跑滿了所有執行緒資源,但是執行時間很短。這是因為本case進行編譯分析的過程中,僅修改了一行程式碼來觸發編譯。因編譯工作量很小,所以這幾列很細。
小結:我們看到,Ninja
編譯啟動比較快,這表明Ninja
對.ninja
檔案的讀取解析並不敏感。整個過程也沒有看到顯著的耗時點。且最後面編譯量很小,表明Ninja
能夠確保增量編譯、未更新不編譯。
本節完成點題——Android系統編譯優化:使用Ninja加快編譯。
根據前面分析的小結,可以總結效能瓶頸:
利用Ninja
進行編譯優化的思路是,大多數場景,可以捨棄Kati的工作,僅執行Ninja的工作,以節省掉60%以上的時間。其核心思路,也是制約條件,即在不影響編譯正確性的前提下,捨棄不必要的Kati編譯工作。
Ninja
直接基於.ninja
檔案進行編譯來改善耗時:結合前面的分析,容易想到,如果目標被構建前,能夠確保mk檔案沒有更新也不需要重新生成一長串的最終編譯目標(即.ninja),那麼make
命令帶來的Soong bootstrap、Kati等工作完全是重複的冗餘的——這個性質Soong和Kati自己識別不出來,它們會重複工作一次。
既重新生成.ninja是冗餘的,那麼直接命令編譯系統根據指定的.ninja進行編譯顯然會節省大量的工作耗時。ninja命令is the key:
使用原始碼中自帶的ninja:
./prebuilts/build-tools/linux-x86/bin/ninja --version 1.8.2.git
對比最上面列出的make
命令的編譯,這裡用ninja編譯同樣的目標:
time ./prebuilts/build-tools/linux-x86/bin/ninja -j 57 -v -f out/combined-full_xxxxxx.ninja services framework
ninja自己識別出來CPU平臺後,預設使用-j58。這裡為了對比上面的m命令,使用-j57編譯
-f引數指定.ninja檔案。它是編譯組態檔,在Android中由Kati生成。這裡檔名用'x'替換修改
編譯結果,對比上面的m
,有三倍的提升:
real 7m57.835s
user 97m12.564s
sys 8m31.756s
編譯耗時為8分半,僅make的三分之一。As we can see,當能夠確保編譯設定沒有更新,變更僅存在於原始碼範圍時,使用Ninja直接編譯,跳過Kati可以取得很顯著的提升。
直接使用ninja:
./prebuilts/build-tools/linux-x86/bin/ninja -j $MAKE_JOBS -v -f out/combined-*.ninja <targets...>
這裡找了一個其他專案的編譯Demo,該Demo的特點是本身程式碼較簡單,編譯設定也較簡單,整體編譯工作較少,通過make編譯的大部分耗時來自soong、make等工具自身的消耗,而真正執行編譯的ninja耗時佔比極其低。由於ninja本身跳過了soong,因此可以跳過這一無用的繁瑣的耗時。可以看到下面,ninja編譯iperf僅花費10秒。這個時間如果給soong來編譯,預熱都不夠。
$ -> f_ninja_msf iperf Run ninja with out/combined-full_xxxxxx.ninja to build iperf. ====== ====== ====== Ninja: ./prebuilts/build-tools/linux-x86/bin/ninja@1.8.2.git Ninja: build with out/combined-full_xxxxxx.ninja Ninja: build targets iperf Ninja: j72 ====== ====== ====== time /usr/bin/time ./prebuilts/build-tools/linux-x86/bin/ninja -j 72 -f out/combined-full_xxxxxx.ninja iperf [24/24] Install: out/target/product/xxxxxx/system/bin/iperf 53.62user 11.09system 0:10.17elapsed 636%CPU (0avgtext+0avgdata 5696772maxresident) 4793472inputs+5992outputs (4713major+897026minor)pagefaults 0swaps real 0m10.174s user 0m53.624s sys 0m11.096s
下面給出soong編譯的恐怖耗時:
$ -> rm out/target/product/xxxxxx/system/bin/iperf $ -> time m iperf -j72 ... [100% 993/993] Install: out/target/product/xxxxxx/system/bin/iperf #### build completed successfully (14:45 (mm:ss)) #### real 14m45.164s user 23m40.616s sys 11m46.248s
As we can see,m和ninja一個是10+ minutes,一個是10+ seconds,比例是88.5倍。
以上就是Android系統優化Ninja加快編譯的詳細內容,更多關於Android Ninja加快編譯的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45