如何查看編譯時間
Optimization Level
設置xcode編譯的線程數
Debug Information Format
將Build Active Architecture Only改為Yes
將Valid Architecture改為arm64,arm64e
二進制化
增量編譯
分布式編譯
其它
如何查看編譯時間
終端內輸入:
defaults write com.apple.dt.Xcode ShowBuildOperationDuration YES
然后你在編譯的時候點擊xcode頂部的那個進度條,當編譯完成的時候就能查看編譯時間。
Optimization Level
這個是xcode Built Setting里的一個參數,Optimization Level是指編譯器的優化層度,優化后的代碼效率比較高,但是可讀性比較差,且編譯時間更長。 它一共有以下幾個選項:
- None: 編譯器不會嘗試優化代碼,當你專注解決邏輯錯誤、編譯速度快時使用此項。
- Fast: 編譯器執行簡單的優化來提高代碼的性能,同時最大限度的減少編譯時間,該選項在編譯過程中會使用更多的內存。
- Faster: 編譯器執行所有優化,增加編譯時間,提高代碼的性能
- Fastest: 編譯器執行所有優化,改善代碼的速度,但會增加代碼長度,編譯速度慢。
- Fastest, Smallest: 編譯器執行所有優化,不會增加代碼的長度,它是執行文件占用更少內存的首選方案
所以說我們平時開發的時候可以選擇使用None來不給代碼執行優化,這樣既可以減少編譯時間,又可以看出你代碼哪里有性能問題。
而你的release版應該選擇Fastest, Smalllest,這樣既能執行所有的優化而不增加代碼長度,又能使執行文件占用更少的內存。
pod里的Optimization Level
我們在使用pod的時候,每一個pod其實都是一個target,它有自己的Optimization Level。cocoapods默認給每一個pod的Optimization Level設置的是Fastest, Smallest,也就是說執行所有的優化和減少內存占用空間。
這樣我們在開發的時候會有兩個問題:一個是debug的時候無法輸出pod源碼里面的變量值,因為編譯器已經給代碼做了優化,它無法再記錄你的變量值了。
還有一個就是編譯時間長,拿我現在的工程來說,如果把所有pod的Optimization Level選項設置成None的話編譯時間為2分30秒,如果為默認的Fastest, Smallest的話時間為3分15秒。
把所有pod的的Optimization Level設置為None只需在Podfile里加入以下代碼即可(其中的"Dev"為你項目的Scheme):
post_install do |installer|
installer.pods_project.build_configurations.each do |config|
if config.name.include?("Dev")
config.build_settings['GCC_OPTIMIZATION_LEVEL'] = '0'
end
end
end
平均節省時間45秒,20%
設置xcode編譯的線程數
defaults write xcodebuild PBXNumberOfParallelBuildSubtasks 8
defaults write xcodebuild IDEBuildOperationMaxNumberOfConcurrentCompileTasks 8
defaults write com.apple.xcode PBXNumberOfParallelBuildSubtasks 8
defaults write com.apple.xcode IDEBuildOperationMaxNumberOfConcurrentCompileTasks 8
XCode默認使用與CPU核數相同的線程來進行編譯,但由于編譯過程中的IO操作往往比CPU運算要多,因此適當的提升線程數可以在一定程度上加快編譯速度。
平均節省時間15秒,8%
Debug Information Format
在工程對應Target的Build Settings中,找到Debug Information Format這一項,將Debug時的DWARF with dSYM file改為DWARF。
這一項設置的是是否將調試信息加入到可執行文件中,改為DWARF后,如果程序崩潰,將無法輸出崩潰位置對應的函數堆棧,但由于Debug模式下可以在XCode中查看調試信息,所以改為DWARF影響并不大。這一項更改完之后,可以大幅提升編譯速度。
其實Debug Information Format就是表示是否生成.dSYM文件,也就是符號表。如果為DWARF就表示不生成.dSYM文件。
This setting controls the format of debug information used by the developer tools. [DEBUG_INFORMATION_FORMAT]
DWARF - Object files and linked products will use DWARF as the debug information format. [dwarf]
DWARF with dSYM File - Object files and linked products will use DWARF as the debug information format, and Xcode will also produce a dSYM file containing the debug information from the individual object files (except that a dSYM file is not needed and will not be created for static library or object file products). [dwarf-with-dsym]
下面這句雖然能修改所有pod的Debug Information Format為DWARF,但是是沒用的,主要還是看主工程里的Debug Information Format的設置。主工程如果為DWARF with dSYM file也會為pod里的代碼生成符號表的。如上面的官方描述所說如果為.a的靜態文件的話是不會生成符號表的。
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
if config.name == 'Dev'
config.build_settings['DEBUG_INFORMATION_FORMAT'] = 'dwarf'
end
end
end
end
平均節省時間7秒,5%
將Valid Architecture改為arm64,arm64e
限制可能被支持的指令集的范圍,也就是Xcode編譯出來的二進制包類型最終從這些類型產生,而編譯出哪種指令集的包,將由Architectures與Valid Architectures(因此這個不能為空)的交集來確定。
目前iOS移動設備指令集:
2018 A12芯片arm64e : iphone XS、 iphone XS Max、 iphoneXR
2017 A11芯片arm64: iPhone 8, iPhone 8 Plus, and iPhone X
2016 A10芯片arm64:iPhone 7 , 7 Plus, iPad (2018)
2015 A9芯片arm64: iPhone 6S , 6S Plus
2014 A8芯片arm64: iPhone 6 , iPhone 6 Plus
2013 A7芯片arm64: iPhone 5S
armv7s:iPhone5|iPhone5C|iPad4(iPad with Retina Display)
armv7:iPhone4|iPhone4S|iPad|iPad2|iPad3(The New iPad)|iPad mini|iPod Touch 3G|iPod Touch4
將Build Active Architecture Only改為Yes
這一項設置的是是否僅編譯當前架構的版本,如果為No,會編譯所有架構的版本。需要注意的是,此選項在Release模式下必須為No,否則發布的ipa在部分設備上將不能運行。這一項更改完之后,可以顯著提高編譯速度。
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
if config.name == 'Dev'
config.build_settings['ONLY_ACTIVE_ARCH'] = 'YES'
end
end
end
end
平均節省時間80秒,26%
二進制化
什么叫二進制化,其實就是把源碼編譯為靜態庫或動態庫。也就是我們平常使用的.framework和.a文件,這些庫都是已經編譯好的,所以當你pod update或者pod install,就不用再重新編譯一遍那么多文件了,能夠顯著減少編譯時間。
pod-package
:可以將任意的 pod 打包成 Static Library,省去重復編譯的時間,一定程度上可以加快編譯時間
Carthage
增量編譯
Buck
:是一套通用的構建系統,由 Facebook 開源。最大的特色是智能的增量編譯可以極大地提高構建速度。最早聽說 Buck 的時候,它還只能用在安卓上,現在已經適配了 iOS。
它能增快構建速度的主要原因是緩存了編譯結果,通過持續監視項目目錄的文件變化,每次編譯時只編譯有改動的文件。
Bazel 跟 Buck 很相似,是 Google 開源的,優缺點跟 Buck 都差不多,不再詳細說了。
distcc 分布式編譯
原理是把一部分需要編譯的文件發送到服務器上,服務器編譯完成后把編譯產物傳回來。我嘗試了一下比較出名的 distcc,搭建過程比較簡單,最后也能成功地把編譯任務分派到內網的多臺服務器上。但是其他編譯服務器的 CPU 占用總是很低,只有 20% 左右;也就是說分派任務的速度甚至還趕不上服務器編譯的速度,分派任務然后回傳編譯產物這個過程所耗費的時間超過了本地直接編譯。不停調整參數反復試驗了很多次,最后發現編譯時間完全沒有變快,甚至還有點變慢了。可能以我們目前項目的規模并不適合使用分布式編譯。
其它方案
CCache是一個能夠把編譯的中間產物緩存起來的工具,而且比較穩定,因此可以打打提高編譯速度。但是CCache不支持clang module,因此需要關閉項目中的Enable Modules,同時對于cocoapods管理的第三方庫,也需要處理clang module的問題。具體使用方法可以參考文章:使用CCache讓打包飛起來
參考:
http://www.cocoachina.com/articles/19665
https://www.zybuluo.com/qidiandasheng/note/587124
http://www.lxweimin.com/p/c9e3fb3dfa53