最近網(wǎng)上閑逛永脓,發(fā)現(xiàn)這篇文章挺好的。翻譯一下 以后備用
1 函數(shù)和表達(dá)式的類型檢查
swift編譯速度緩慢大部分是因?yàn)轭愋蜋z查耗時(shí)長(zhǎng)搅吁。默認(rèn)情況下Xcode不會(huì)顯示編譯慢的代碼落午。你可以通過(guò)指令來(lái)顯示編譯慢的函數(shù)和表達(dá)式,
添加如下指定到build settings
-> Other Swift Flag
-
-Xfrontend -warn-long-function-bodies=100
(100
這里意思100ms,修改這個(gè)值主要根據(jù)你電腦和項(xiàng)目的速度) -Xfrontend -warn-long-expression-type-checking=100
編譯運(yùn)行界拦,可以看到如下結(jié)果
下一步就是對(duì)應(yīng)John Sundell 和
Robert Gummesson 文章 去優(yōu)化編譯器提示的問(wèn)題代碼享甸。
提示:這個(gè)功能在啟動(dòng)模塊優(yōu)化的情況下無(wú)法工作梳侨,所以請(qǐng)關(guān)閉模塊優(yōu)化Whole Module Optimization
??Sources:
- Guarding Against Long Compiles
- Measuring Swift compile times in Xcode 9 · Jesse Squires
- Improving Swift compile times — Swift by Sundell
- Swift build time optimizations?—?Part 2
編譯緩慢的文件
上面描述如何知道函數(shù)和表達(dá)式的編譯時(shí)間,不過(guò)去知道文件的編譯速度也是很有意思的蚯嫌。
但是 Xcode 沒(méi)有響應(yīng)操作的UI界面割坠,因此你可以可以通過(guò)CLI來(lái)編譯項(xiàng)目
xcodebuild -destination 'platform=iOS Simulator,name=iPhone 8' \
-sdk iphonesimulator -project YourProject.xcodeproj \
-scheme YourScheme -configuration Debug \
clean build \
OTHER_SWIFT_FLAGS="-driver-time-compilation \
-Xfrontend -debug-time-function-bodies \
-Xfrontend -debug-time-compilation" | \
tee profile.log
如果你使用 workspace 請(qǐng)使用-workspace YourProject.xcworkspace
去替換 -project YourProject.xcodeproj
然后使用如下代碼來(lái)提取一些有趣的統(tǒng)計(jì)數(shù)據(jù):
awk '/Driver Compilation Time/,/Total$/ { print }' profile.log | \
grep compile | \
cut -c 55- | \
sed -e 's/^ *//;s/ (.*%) compile / /;s/ [^ ]*Bridging-Header.h$//' | \
sed -e "s|$(pwd)/||" | \
sort -rn | \
tee slowest.log
你最終得到一個(gè)slowest.log
文件妒牙,其中包括項(xiàng)目中的文件以及他們的編譯時(shí)間。類似
2.7288 ( 0.3%) {compile: Account.o <= Account.swift }
2.7221 ( 0.3%) {compile: MessageTag.o <= MessageTag.swift }
2.7089 ( 0.3%) {compile: EdgeShadowLayer.o <= EdgeShadowLayer.swift }
2.4605 ( 0.3%) {compile: SlideInPresentationAnimator.o <= SlideInPresentationAnimator.swift }
提示: 和上面的提示一樣
??Sources:
只構(gòu)建一個(gè)活躍的架構(gòu) (Build active architecture only)
這個(gè)設(shè)置是默認(rèn)的敢朱,不過(guò)你要檢查一下是否設(shè)置正確摩瞎。如下:
??Sources:
dSYM生成
默認(rèn)新的項(xiàng)目中拴签,所有的build不會(huì)生成sSYM文件旗们。不過(guò)有時(shí)候當(dāng)我們運(yùn)行在一個(gè)去分析崩潰的而且不能斷點(diǎn)調(diào)試的真機(jī)上,這是相當(dāng)有用的岸梨。(確實(shí) 要點(diǎn)個(gè)贊 這個(gè)tip)
推薦設(shè)置:
??Sources:
整個(gè)模塊優(yōu)化
另外一些平常的技巧:
在debug配置中改變
Optimization Level
為Fast, Whole Module Optimization
-
只在debug配置下為
Other Swift Flags
添加-Onone
標(biāo)記
它指示編譯器器做了如下操作:
- 一個(gè)模塊里的所有源文件都運(yùn)行在一個(gè)編譯任務(wù)中曹阔,而不是一個(gè)原本件對(duì)應(yīng)一個(gè)編譯任務(wù)。
- 減少了并行性赃份,但也減少了重復(fù)的工作
- 這是更快的bug; 但我們需要稍作重復(fù)的工作抓韩。改進(jìn)它是以后的目標(biāo)
注意的是在這設(shè)置下可能有的小改變?cè)隽繕?gòu)建中顯的有點(diǎn)更緩慢。不過(guò)在最壞的情況下你會(huì)看到巨大的提速(項(xiàng)目中有很多2x)
??Sources:
- Developear - Speeding Up Compile Times of Swift Projects
- Slava Pestov on Twitter: “@iamkevb It runs one compiler job with all source files in a module instead of one job per source file”
針對(duì)Coco'apod做整個(gè)模塊優(yōu)化
如果你使用Cocoapod渺蒿,你應(yīng)該考慮在你的pod項(xiàng)目沒(méi)有優(yōu)化的情況下啟用WNO,你可以在你的Podfile
文件中添加如下post_install
鉤子
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
if config.name == 'Debug'
config.build_settings['OTHER_SWIFT_FLAGS'] = ['$(inherited)', '-Onone']
config.build_settings['SWIFT_OPTIMIZATION_LEVEL'] = '-Owholemodule'
end
end
end
end
然后運(yùn)行pod install
. 確保在此更改前后比較構(gòu)建時(shí)間彪薛,以確認(rèn)有改進(jìn)。
三方依賴
這里有2種方式去在你的項(xiàng)目中嵌入三方依賴
- 作為那種你每次clean就要重新操作的原件(例如Cocoapod,git submodules,復(fù)制粘貼的代碼少态,app target 依賴的子項(xiàng)目的內(nèi)部庫(kù))
- 作為一個(gè)與構(gòu)建的 framework/library(例如 Carthage 易遣,第三方不想提供源代碼發(fā)布的靜態(tài)庫(kù))
CocoaPods 是專為iOS 設(shè)計(jì)最流行的依賴管理,但是導(dǎo)致很長(zhǎng)的編譯時(shí)間侨歉。作為第三方庫(kù)的源代碼揩魂,在大多數(shù)情況下。每次clean都要重新編譯牵舵。通常情況下倦挂,你不需要這樣做。但是實(shí)際上方援,確實(shí)有必要這么做(如 分支切換 Xcode bug)
盡管Carthage非常難用犯戏,但是如果你在乎構(gòu)建時(shí)間的話祖很,這是一個(gè)好的選擇漾脂。僅僅當(dāng)你更改依賴列表時(shí)候(添加刪除依賴,升級(jí)版本)才構(gòu)建外部依賴庫(kù)笨鸡。這需要可能5或者15分鐘坦冠,但是比起嵌入代碼到Cocoapod你要少做很多。
?? Sources:
- time spent waiting for Xcode to finish builds ??
模塊化
swift的增量編譯并不完美辙浑。有一些項(xiàng)目判呕,我們改變一個(gè)字符串導(dǎo)致整個(gè)增量構(gòu)建過(guò)程中重新編譯。它可以被調(diào)試和改變侠草。但很多好的工具不能被使用边涕。
為了避免這樣的問(wèn)題,你需要將你的項(xiàng)目劃分到不同的模塊中功蜓。在iOS 中動(dòng)態(tài)庫(kù)和靜態(tài)庫(kù)都可以(Xcode9 swift支持靜態(tài)庫(kù))
讓我們假如你的項(xiàng)目依賴一個(gè)叫DatabaseKit
的內(nèi)部framework。這種方法保證當(dāng)你項(xiàng)目更改一些內(nèi)容重新編譯的時(shí)候童社。DatabaseKit
在增量構(gòu)建中不會(huì)重新編譯端衰。
??Sources:
XIBs
xib/sb vs 純代碼 這是一個(gè)非常熱門的話題旅东。不過(guò)我們不會(huì)在這里充分討論十艾。有趣的是,當(dāng)你修改IB中的內(nèi)容忘嫉,這有這個(gè)文件被編譯。另一方面康吵,如果你修改UIView子類的一個(gè)公共方法swift編譯器會(huì)決定重新編譯大部分項(xiàng)目。
??Sources:
Xcode Schemes
通常項(xiàng)目設(shè)置有3個(gè)targets
- App
- AppTests
- AppUITests
在一個(gè)scheme中處理是很好的但是我們可以做的更好同辣。我們最近的設(shè)置是由3個(gè)scheme組成惭载。
APP
使用cmd - b上構(gòu)建應(yīng)用程序的時(shí)候只運(yùn)行單元測(cè)試描滔。用于短迭代,例如在UI代碼中含长,只需要構(gòu)建所需的代碼。
App - Unit Test Flow
當(dāng)構(gòu)建app 和 單元測(cè)試的時(shí)候颅眶,只運(yùn)行單元測(cè)試田弥。在編寫單元測(cè)試的時(shí)候非常有用偷厦。因?yàn)楫?dāng)你構(gòu)建單元測(cè)試的時(shí)候能立刻發(fā)現(xiàn)錯(cuò)誤,而不用運(yùn)行他們只泼。
App - All Tests Flow
構(gòu)建app 和所有的測(cè)試的時(shí)候请唱。運(yùn)行所有的測(cè)試。UI測(cè)試的時(shí)候非常有用聚至。
??Sources:
使用新的Xcode構(gòu)建系統(tǒng)
Xcode9 蘋果介紹了一種新的構(gòu)建系統(tǒng)本橙。目前是預(yù)覽版,默認(rèn)不使用贷币。這筆默認(rèn)構(gòu)建系統(tǒng)明顯更快。在Xcode文件菜單中選擇Workspace or Project Settings 去可以切換都新的構(gòu)建系統(tǒng)偶摔。
??Sources:
顯示Xcode的編譯時(shí)間
最后促脉,為了讓我們知道我們的構(gòu)建系統(tǒng)是否提升了。我們需要在Xcode界面上顯示構(gòu)建時(shí)間亡呵。運(yùn)行如下命令顯示:
$ defaults write com.apple.dt.Xcode ShowBuildOperationDuration -bool YES
一旦我們這樣做了硫戈。cmd b我們可以看見(jiàn)
我推薦比較相同條件下的構(gòu)建時(shí)間
1 退出Xcode
2 清除派生的數(shù)據(jù)
3 在Xcode項(xiàng)目中打開你的項(xiàng)目
4 在Xcode打開或索引階段完成后立即開始構(gòu)建。第一個(gè)方法似乎更具有代表性汁胆,因?yàn)閺腦code 9構(gòu)建開始也執(zhí)行了索引霜幼。
可選擇的,你可以在命令行下運(yùn)行
$ time xcodebuild other params
??Sources: