swift工程編譯越來越慢,原來...
查看編譯時間
方法1. 在 target -> Build Settings -> Other Swift Flags 添加編譯設置
-Xfrontend -debug-time-function-bodies
查找耗時代碼
xcodebuild -workspace yourWorkspaceName.xcworkspace -scheme schemeName clean build 2>&1 |egrep "\d.\dms"|sort -nr > times.txt
sort -nr 會按照時間大小排序,當編譯完成后,times.txt里可以查看到各個方法編譯的時間
然后解決掉前面比較耗時的代碼 編譯就會相對快了
方法2. 不在Build Settings中添加編譯設置
xcodebuild -workspace yourWorkspaceName.xcworkspace -scheme schemeName clean build OTHER_SWIFT_FLAGS="-Xfrontend -debug-time-function-bodies" | egrep "\d.\dms" | egrep -v "\b0.0ms" > times.txt
此處增加的 egrep -v "\b0.0ms" 可以排除掉編譯時間為0.0ms的方法
-workspace yourWorkspaceName.xcworkspace 在沒有workspace 可以省略
-scheme schemeName 沒有workspace切僅一個target時可省略
以下總結了我自己遇到的幾種比較耗時的情況: (新建的工程進行以下測試時 有些不是很明顯,所以在你發現你的工程編譯越來越慢時,可以通過以上的方法 ,來對癥下藥)
1.lazy屬性
//
private lazy var label: UILabel = {
let l = UILabel()
l.font = UIFont.systemFontOfSize(19)
return
}()
//
private lazy var labe1: UILabel = {
$0.font = UIFont.systemFontOfSize(19)
return $0
}(UILabel())
private var label2: UILabel!
self.label2 = UILabel()
self.label2.font = UIFont.systemFontOfSize(19)
之前在解決編譯慢時 完全沒想到 lazy屬性 會有影響,編譯時間多大200ms+, 如果僅被編譯一次,那就無關痛癢
當一個類使用的地方多的時候,這個累會多次進行編譯,假如一個類在10處有使用,則該類會被編譯20次:scream:, 200ms * 20 = 4s, 這樣算起來就... 大家可以自己想象
所以最后筆者把所有的lazy屬性都換掉了 :smile:
2.數組操作
// 321.4ms
func plus() {
let arr1 = ["1"]
let arr2 = ["2"]
let arr3 = ["3"]
let result = arr1 + arr2 + arr3
}
// 3.1ms
func append() {
let arr1 = ["1"]
let arr2 = ["2"]
let arr3 = ["3"]
var result = arr1
result.appendContentsOf(arr2)
result.appendContentsOf(arr3)
}
3.optional
// 2.6ms ?? 與其它操作符一起用 -- 此處可能會耗時,筆者遇到這里耗時200ms+的情況,修改了后好了些
var optionalInt: Int? = 10
let plus = (optionalInt ?? 0) + 10
// 0.5ms 使用變量將?? 的值存起來 再進行預算
var optionalInt: Int? = 10
var nonnullInt = optionalInt ?? 0
let plus = nonnullInt + 10
//10.8ms 直接將??運算的結果賦給屬性 可能會很耗時!!!
let label = UILabel()
let optionalStr : String? = nil
label.text = optionalStr ?? ""
// 0.3ms ??運算的結果用變量存起來再賦給屬性
let label = UILabel()
let optionalStr : String? = nil
let displayText = optionalStr ?? ""
label.text = displayText
4.map
//20.3ms
func testLazyMap() {
let intArr = (0..<100).map{$0}
let lazyMapResult: [String] = intArr.`lazy`.map{ String($0) }
}
7.5ms
func testDirectMap() {
let intArr = (0..<100).map{$0}
let lazyMapResult: [String] = intArr.map{ String($0) }
}
lazy 比非lazy相對耗時,在編譯慢時時間相差會比較明顯
206.6ms
func test_appendLazyMapArray() {
let intArr = (0..<100).map{$0}
var result: [String] = []
result.appendContentsOf(intArr.lazy.map{ String($0) })
}
25.9ms
func test_appendMapArray() {
let intArr = (0..<100).map{$0}
var result: [String] = []
result.appendContentsOf(intArr.map{ String($0) })
}
直接append 帶lazy的數組和不帶lazy的數組,不帶lazy的方式編譯快
7.4ms
func test_appendMapedVar() {
let intArr = (0..<100).map{$0}
var result: [String] = []
let maped = intArr.map{ String($0) }
result.appendContentsOf(maped)
}
33.0ms
func test_appendLazyMappedVar() {
let intArr = (0..<100).map{$0}
var result: [String] = []
let maped = intArr.lazy.map{ String($0) }
result.appendContentsOf(maped)
}
帶lazy的同樣比無lazy的慢
5.字符串操作
4.9ms
func plus_asString(){
let string: NSString = "123"
let result = "當前城市" + (string as String)
}
0.3ms
func plus_stringVAR(){
let nsstring: NSString = "123"
let string = nsstring as String
let result = "當前城市" + string
}
17.2ms
func stringFormate(){
let nsstring: NSString = "123"
let string = nsstring as String
let result = "當前城市\(string)"
}
這幾種字符串拼接 相差無幾
6.復雜一點的集合 eg:字典
這里引入 debugging-slow-swift-compile-times 的一個:chestnut:
//50612.1ms
[
"A" : [
["B": [1, 2, 3, 4, 5]],
["C": [ ]],
["D": [ ["A": [ 1 ]]]]
]
]
// 8.8ms
[
"A" : [
["B": [1, 2, 3, 4, 5]] as [String: [Int]],
["C": [ ]] as [String: [Int]],
["D": [ ["A": [ 1 ]] as [String: [Int]]]] as [String : [[String: [Int]]]]
]
]
在解決掉上面這幾種情況后,工程編譯沒那么慢了,心情也好多了
來自:http://www.jianshu.com/p/71bbc843abdb