作者連接: 興趣使然的程序員:http://www.reibang.com/users/94b6bbf8765a/latest_articles
0x00 遇到編譯速度問題
蘋果公司在大力推廣swift語言, 但是swift語言差強人意.
從swift1.2開始在實際項目中引入swift語言, 已經(jīng)有一年多了, 最近遇到一個問題, 就是項目的編譯速度越來越慢,達到了20分鐘左右. 網(wǎng)上也有很多人說類似的問題.
編譯速度直接影響開發(fā)效率. 因為開發(fā)工作需要專注, 編譯的時候, 程序員們大多都是在等, 這簡直是在浪費生命.
進行了一定的研究和實驗以后, 發(fā)現(xiàn)了一些可能的改進方式. 這些改進方式對于發(fā)現(xiàn)同類問題的人, 可以做些參考.
0x01 檢查編swift譯速度
- 設置在編譯配置, 輸出編譯時間信息. Other Swift Flas 增加設置: -Xfrontend -debug-time-function-bodies;
- 執(zhí)行build, 將build信息存入文本文檔 debug_buld_info.txt;
- 提取出所有方法的編譯時間,將信息按照編譯時間由長到短排序: grep [1-9].[0-9]ms debug_build_info.txt | sort -nr >> build_slow.txt;
- 檢查編譯時間過長的方法, 進行修改;
- 通過檢查, 發(fā)現(xiàn)項目中編譯時間超過500ms的方法有很多, 這是編譯速度慢的一大元兇. 重點對他們進行了修改調(diào)整.
0x02 發(fā)現(xiàn)的影響swift編譯速度的因素
1. 編譯參數(shù)
是否開啟了swift編譯優(yōu)化選項: whole module optimization, 會在一定程度上影響編譯速度. 可以選擇在Debug上關閉. 但是在Release編譯的時候, 不適合關閉.
2. 類型推導:
類型推導可能是導致編譯速度變慢的原因. 網(wǎng)上有個很離譜的一個例子, 大約十多行的代碼, 編譯時間超過24小時, 代碼內(nèi)容只是做了一個嵌套字典定義初始化. 該bug在今年4月份發(fā)現(xiàn), 目前(10月)依舊存在. 猜測swift在設計理論上存在缺陷, 所以這個問題無解. 下面是類型推導的示例:
- 慢
let createDate = NSDate(timeIntervalSince1970:interval) //變量(常量)的聲明發(fā)生了類型推導
if (doubleNum/60 < 1) { //表達式在計算中發(fā)生了類型推導
var strings: [String] = [] //初始化值進行了類型推導
- 快
let createDate:NSDate = NSDate(timeIntervalSince1970:interval)
if (doubuleNum/60.0 < 1.0) {
var strings: [String] = [String]()
3. 需要計算的表達式
如果表達式中存在常量的表達式, 編譯器可能會在編譯時進行計算, 如果我們幫編譯器算出, 會提高編譯速度.
- 慢
let t=24*60*60*1000
- 快
let t=86400000 //24*60*60*1000
4. 復雜的表達式
復雜表達式的處理, 是swift編譯器的弱項. 稍微復雜點的表達式, 甚至會編譯失敗, 很多人應該遇到過. 同時, 復雜表達式也會導致編譯速度變慢.
- 慢
txt = (note?.text ?? "") + "\n" + selectedText
- 快
txt = note?.text ?? ""
txt += "\n"
txt += selectedText
5. 過長的鏈式操作
- 慢
r=a.func1().func2().func3()
- 快
let b=a.func1()
let c=b.func2()
r=c.func3()
6. 數(shù)組+操作
數(shù)組的+運算符的使用, 會嚴重降低編譯速度. 雖然寫法優(yōu)雅, 但是目前不合適. 只能用相對丑陋的插入操作進行處理.
- 慢
let all = redBooks + greenBooks + yellowBooks
- 快
var all:[Book]=[Book]() //避免類型推導
for b in redBokks {
all.append(s) //用插入替換+
}
for b in greenBokks {
all.append(s)
}
for b in yellowBokks {
all.append(s)
}
7. 打印函數(shù)
不debug的時候, 將print注釋掉
8. 代碼中的警告
一定要把代碼中得警告都處理掉
0x03 其他
1. 補充
另外還有一些提高編譯速度的方法, 但是不是針對Swift, oc同樣有效, 所以沒有細說. 比如用framwork/lib 替換需要編譯的cocoapods管理的代碼(這個很明顯), 設置多線程編譯, 用性能更好的電腦, 將Debug Information Format改為DWARF, Build Active Architecture Only改為Yes等等.
2. 感想
以前上學的時候, 學過編譯原理, 很喜歡這門課, 但是 沒想到這次會有所幫助, 在分析編譯速度的時候, 能夠有一些思路, 這門課有莫大的幫助.
3. 參考
- https://panupan.com/2016/02/16/how-to-speed-up-slow-swift-compile-times/
- https://thatthinginswift.com/debug-long-compile-times-swift/
- https://www.amazon.cn/%E7%BC%96%E8%AF%91%E5%8E%9F%E7%90%86-Alfred-V-Aho/dp/B001NGO85I/ref=sr_1_1?ie=UTF8&qid=1476589755&sr=8-1&keywords=%E7%BC%96%E8%AF%91%E5%8E%9F%E7%90%86
- http://blog.csdn.net/zhaoxy_thu/article/details/30073485