Swift編譯速度(推斷速度)優(yōu)化總結(jié)
測試基于2018款MacBook pro(主頻2.6的i7), Xcode 11.3, Swift 5.1.3
測試時(shí)在 OTHER_SWIFT_FLAGS 里加入:
-Xfrontend
-warn-long-expression-type-checking=100
還有一個(gè)推斷方法時(shí)間的Flag我沒用, 那個(gè)加上去到處都是超時(shí), 根本改不完...
實(shí)際上改100個(gè)超過100ms的也僅僅快了10秒, 改1000個(gè)以上才能明顯感覺到變快...只能說日常開發(fā)注意了
- 不要嵌套閉包
Swift推斷閉包(方法)需要把內(nèi)部所有代碼都推斷完才能推斷出閉包的類型, 這時(shí)候推斷效率會變得奇低, 速度最低時(shí)只有正常情況下的1/10, 如:
fileprivate lazy var bindPhoneCell: AccountBindButton = {
let cell = AccountBindButton()
cell.rx.controlEvent(.touchUpInside).subscribe { [weak self] (_) in
...
}.disposed(by: disposeBag)
return cell
}()
- 類型屬性的初始化不能過于復(fù)雜, 大概是閉包里超過7行, 類似于:
class contactView: UIView {
private lazy var wechatContact: VerticalAlignButton = {
let button = VerticalAlignButton(type: .custom)
button.innerSpace = 12
button.corner(byRoundingCorners: .allCorners, radius: 8.adp.cgFloat)
button.layer.masksToBounds = true
button.imageEdgeInsets = UIEdgeInsets(top: 6, left: 0, bottom: 0, right: 0)
button.setImage(UIImage(named: "icon_wechat_about"), for: .normal)
button.setImage(UIImage(named: "icon_wechat_about"), for: .selected)
button.setTitleColor(UIColor.Global.messageTextColor, for: .normal)
button.titleLabel?.font = UIFont.Global.fontDFYuanGBW5(with: 16)
button.backgroundColor = UIColor.Global.whiteBGColor
return button
}()
}
- 屬性能不用閉包盡量不要用閉包(帶閉包的)初始化, 比如2里面那種, 或者類似于:
private lazy var wechatContact = VerticalAlignButton(type: .custom).config {
$0.innerSpace = 12
}
但寫起來是真的快樂, 快樂就完事了
閉包的類型寫不寫完整區(qū)別不大, 編譯器為了驗(yàn)證類型是否正確總是會自己推斷一遍的
有返回值的閉包比無返回值的閉包需要更長的推斷時(shí)間(大概1.5到2倍), 所以上述2里的例子改寫成3里的例子會快一些, 但除非閉包非常復(fù)雜否則差別不大
重載的函數(shù)會增加3到10倍的推斷時(shí)間, 比如:
Int(floor(progress * 100)) 和 (progress * 100).floor.int
點(diǎn)名批評一下Snapkit和RxSwift這兩個(gè)用了大量重載函數(shù)的庫, 超過100ms的代碼一半都是這兩個(gè)庫的閉包方法, 還有WCDB.swift的where語句也難以推斷, 簡單的像:
Properties.userId == 0 && Properties.resourceId == 1 && Properties.chapterId == 2
就得推斷140ms, 服了
- 短表達(dá)式的推斷速度:
只讀屬性 > 調(diào)用protocol方法快 > 作為泛型參數(shù)傳進(jìn)方法/重載的函數(shù)
比如:
1.double(單獨(dú)寫的double屬性) > 1.double(BinaryInteger的extension) > Double(1)
慢的時(shí)候(嵌套太多的時(shí)候)速度可能會相差上百倍
- 使用Codable的類型創(chuàng)建太多靜態(tài)屬性也會導(dǎo)致推斷時(shí)間變長:
struct Para: Codable {
...
}
extension Para {
static let network: Para(...)//這種靜態(tài)屬性一多就會出現(xiàn)推斷超時(shí)
}
在閉包里使用DEBUG宏也會導(dǎo)致推斷時(shí)間增加, 非常的迷
if/guard 里用,代替&&會提高推斷速度, 看情況用,的時(shí)候編譯器會把if后面的東西當(dāng)成遞進(jìn)的關(guān)系, 而用&&的時(shí)候是平行的關(guān)系