Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save Changzw/055f88454bbafcf0e1d3eed9a7468a70 to your computer and use it in GitHub Desktop.

Select an option

Save Changzw/055f88454bbafcf0e1d3eed9a7468a70 to your computer and use it in GitHub Desktop.
Code samples of common sources of slowdowns for the Swift 2/3 compiler.
//
// The code snippets below showcase common "problem code" that can take a long time to compile.
// These examples were primarily observed in Swift 2/3 and may no longer be relevant in Swift 4 or higher.
//
/// 1. Array concatenation
// Observed by Robert Gummesson - https://medium.com/@RobertGummesson/regarding-swift-build-time-optimizations-fc92cdd91e31#c75c
// Joining two arrays together with the '+' operator can be expensive to compile.
let someArray = ["a", "b"] + ["c", "d"]
/// 2. Extraneous casting
// Observed by Robert Gummesson - https://medium.com/@RobertGummesson/regarding-swift-build-time-optimizations-fc92cdd91e31#60bf
// Avoid casting values to their own type when doing calculations.
// In the example below, the 'hour', 'hourDelta', 'minute', and 'minuteDelta' are already of type CGFloat.
// Build time: 3431.7ms
return CGFloat(M_PI) * (CGFloat((hour + hourDelta + CGFloat(minute + minuteDelta) / 60) * 5) - 15) * unit / 180
// Build time: 3.0ms
return CGFloat(M_PI) * ((hour + hourDelta + (minute + minuteDelta) / 60) * 5 - 15) * unit / 180
/// 3. round()
// Observed by Robert Gummesson - https://medium.com/@RobertGummesson/regarding-swift-build-time-optimizations-fc92cdd91e31#9b8b
// Avoid rounding if it's not necessary for your calculations.
// Build time: 1433.7ms
let expansion = a - b - c + round(d * 0.66) + e
// Build time: 34.7ms
let expansion = a - b - c + d * 0.66 + e
/// 4. Lazy properties
// Observed by Robert Gummesson - https://medium.com/swift-programming/swift-build-time-optimizations-part-2-37b0a7514cbe#beb8
// Assigning the value of a lazy property to a private function that builds it instead of an in-line closure can improve compilation times.
// Before
private(set) lazy var chartViewColors: [UIColor] = [
self.chartColor,
UIColor(red: 86/255, green: 84/255, blue: 124/255, alpha: 1),
UIColor(red: 80/255, green: 88/255, blue: 92/255, alpha: 1),
UIColor(red: 126/255, green: 191/255, blue: 189/255, alpha: 1),
UIColor(red: 161/255, green: 77/255, blue: 63/255, alpha: 1),
UIColor(red: 235/255, green: 185/255, blue: 120/255, alpha: 1),
UIColor(red: 100/255, green: 126/255, blue: 159/255, alpha: 1),
UIColor(red: 160/255, green: 209/255, blue: 109/255, alpha: 1),
self.backgroundGradientView.upperColor
]
// After
// Cumulative build time: 56.3ms
private(set) lazy var chartViewColors: [UIColor] = self.createChartViewColors()
// Build time: 6.2ms
private func createChartViewColors() -> [UIColor] {
return [
chartColor,
UIColor(red: 86/255, green: 84/255, blue: 124/255, alpha: 1),
UIColor(red: 80/255, green: 88/255, blue: 92/255, alpha: 1),
UIColor(red: 126/255, green: 191/255, blue: 189/255, alpha: 1),
UIColor(red: 161/255, green: 77/255, blue: 63/255, alpha: 1),
UIColor(red: 235/255, green: 185/255, blue: 120/255, alpha: 1),
UIColor(red: 100/255, green: 126/255, blue: 159/255, alpha: 1),
UIColor(red: 160/255, green: 209/255, blue: 109/255, alpha: 1),
backgroundGradientView.upperColor
]
}
/// 5. In-line computation
// Observed by Dejan Atanasov - https://hackernoon.com/speed-up-swift-compile-time-6f62d86f85e6#315a
// Avoid doing computations directly in an 'if' statement.
// Before
if number == 60 * 60 {
// ...
}
// After
let number: Double = 60 * 60
if number == 3600 {
// ...
}
// 任何运算式,赋值语句都要加上类型!!! 运算式包括,1,2,3位运算
/// 6. String concatenation
// Observed by Dejan Atanasov - https://hackernoon.com/speed-up-swift-compile-time-6f62d86f85e6#315a
// Favor string interpolation over concatenation (using the '+' operator).
// Before
let url = "https://google.com/" + "path/" + "anotherpath"
// After
let url = "https://google.com/\("path")/\("anotherpath")"
/// 7. Ternary operator
// Observed by Robert Gummesson - https://medium.com/swift-programming/swift-build-time-optimizations-part-2-37b0a7514cbe#56ea
// Favoring 'if'/'else' over the ternary operator could improve compile times.
// Before
return someValue > 3 ? someValue - 2 : someValue + 2
// After
if someValue > 3 {
return someValue - 2
} else {
return someValue + 2
}
/// 8. Nil-coalescing operator
// Observed by Robert Gummesson - https://medium.com/@RobertGummesson/regarding-swift-build-time-optimizations-fc92cdd91e31#ec7d
// Favoring mutable state and multiple 'if'/'else' statements could improve compile times.
// Before
return CGSize(width: size.width + (rightView?.bounds.width ?? 0) + (leftView?.bounds.width ?? 0) + 22, height: bounds.height)
// After
var padding: CGFloat = 22
if let rightView = rightView {
padding += rightView.bounds.width
}
if let leftView = leftView {
padding += leftView.bounds.width
}
return CGSize(width: size.width + padding, height: bounds.height)
/// 9. Function type inference
// Observed by Paul Hudson - https://www.hackingwithswift.com/articles/11/how-to-make-swift-compile-faster
// Using a similar function that takes a more generic argument can improve compile times.
// In the example below, a String initializer that takes an "Any" type is used instead of an operator that takes an "Int" type.
// Compile times can also be further reduced by splitting up the complex expression.
// Before
let sum = [1, 2, 3].map { String($0) }.flatMap { Int($0) }.reduce(0, +)
// After
let sum = [1, 2, 3].map { String(describing: $0) }.flatMap { Int($0) }.reduce(0, +)
// After (splitting up expression)
let numbers = [1, 2, 3]
let stringNumbers = numbers.map { String($0) }
let intNumbers = stringNumbers.flatMap { Int($0) }
let sum = intNumbers.reduce(0, +)
/// 10. Collection type inference
// Observed by Dajan Atanasov - https://hackernoon.com/speed-up-swift-compile-time-6f62d86f85e6#315a
// Manually adding type information to your arrays/dictionaries can improve compile times.
// Before
let someArray = ["a", "b", "c"]
// After
let someArray: [String] = ["a", "b", "c"]
// 任何运算式,赋值语句都要加上类型!!! 运算式包括,1,2,3位运算
var prePadding = 0
//After
var prePadding: Int = 0
let newContents = Language.current == .zh ? contents : contents.reversed()
let newContents: [GlobalBannerContent] = Language.current == .zh ? contents : contents.reversed()
let color1 = colors?.safeObject(at: 0) ?? ""
let color1: String = colors?.safeObject(at: 0) ?? ""
self.rank1stScoreLabel.text = item.score.map{
$0 >= 1_00_00 ?
String(format: "%.2f", Float($0) / 1_00_00.0) + "w" :
String($0)
}
// 加上语义明确的括号
let items: [LiveGiftItem]
items = giftQueryByRoomRsp?.commonGifts?.compactMap { $0 }
.filter { $0.sort ?? 0 > 0 && $0.id != 68 }
.sorted(by: { $0.sort ?? 0 > $1.sort ?? 0 }) ?? []
items = giftQueryByRoomRsp?.commonGifts?.compactMap { $0 }
.filter { $0.sort ?? 0 > 0 && $0.id != 68 }
.sorted(by: { $0.sort ?? 0 > $1.sort ?? 0 }) ?? []
// wtf
return radians / CGFloat.pi * 180.0
return radians / (CGFloat.pi * 180.0)
// attention!!! 编译速度的大坑
String($0) + "/200" // 影响编译速度
"\($0)/200" //p.s. 这个会影响运行时速度
// wtf
let refBounds = bounds.insetBy(dx: -tolerance, dy: -tolerance)
let refBounds: CGRect = bounds.insetBy(dx: -tolerance, dy: -tolerance)
//
var giftSectionViewModels = [GiftSectionViewModel]()
var giftSectionViewModels: [GiftSectionViewModel] = []
//
row = CGFloat((viewModel.dataSource.count - 1) / Int(Self.column) + 1)
let v: Int = (viewModel.dataSource.count - 1) / Int(Self.column) + 1
row = CGFloat(v)
//
let x = delegate?.collectionView?(cv, layout: self, insetForSectionAt: section).left ?? sectionInset.left
let x: CGFloat = delegate?.collectionView?(cv, layout: self, insetForSectionAt: section).left ?? sectionInset.left
//
if danmakuView.queuingCount + danmakuView.animatingCount == 0 {
superview?.isHidden = true
}
let v = danmakuView.queuingCount + danmakuView.animatingCount
if v == 0 {
superview?.isHidden = true
}
//
levelUpExpLabel.text = "距离下一等级还差%d{# Android #}".localized(with: [(data?.nextExp ?? 0) - (data?.curExp ?? 0)])
let exp: Int
if let n = data?.nextExp,
let c = data?.curExp {
exp = n - c
}else {
exp = 0
}
levelUpExpLabel.text = "距离下一等级还差%d{# Android #}".localized(with: [exp])
//
guard let URLStrings = self.allGiftsItems?.compactMap { $0.mp4s?.compactMap { $0 } }.flatMap { $0 }.filter({ $0.count > 0 }) else { return }
let items = allGiftsItems?
.compactMap { $0.mp4s?.compactMap { $0 } }
.flatMap { $0 }
.filter{ $0.count > 0 }
guard let URLStrings = items else { return }
//
statusView.updateUI(with: room.redpacketArray?.compactMap { $0 } ?? [], status: room.callStatus ?? .none)
let items: [RoomRedpacketItem] = room.redpacketArray?.compactMap { $0 } ?? []
statusView.updateUI(with: items, status: room.callStatus ?? .none)
//
vm_.realTimeDataUpdate
.compactMap{ $0.income }
.compactMap{ String($0) }
.bind {[weak self] (v) in
self?.incomeView?.income = v
}
.disposed(by: bag)
let sig: Observable<String> =
vm_.realTimeDataUpdate
.compactMap{ $0.income }
.compactMap{ String($0) }
sig
.bind {[weak self] (v) in
self?.incomeView?.income = v
}
.disposed(by: bag)
// 4 部分
// -----0
mk.width.equalTo(min(viewModel.items
.map(\.title)
.map{ $0.width(for: UIFont.UKIJQara(14)) + 20 }
.reduce(0, +) + 10, UIScreen.main.bounds.width))
// -----1
let length: CGFloat = viewModel.items
.map(\.title)
.map{ $0.width(for: UIFont.UKIJQara(14)) + 20 }
.reduce(0, +) + 10
mk.width.equalTo(min(length, UIScreen.main.bounds.width))
// -----2
let length: CGFloat = viewModel.items
.map(\.title)
.map{ $0.width(for: UIFont.UKIJQara(14)) + 20 }
.reduce(0, +)
let lengthBy10 = length + 10
mk.width.equalTo(min(lengthBy10, UIScreen.main.bounds.width))
// -----3
let length: CGFloat = viewModel.items
.map(\.title)
.map{
let w = $0.width(for: UIFont.UKIJQara(14))
return w + 20
}
.reduce(0, +)
let lengthBy10 = length + 10
mk.width.equalTo(min(lengthBy10, UIScreen.main.bounds.width))
// 1000+
let itemSize = (UIScreen.main.bounds.size.width - CGFloat(15 * 2 + 10 * 3)) / CGFloat(4)
let itemSize = (UIScreen.main.bounds.size.width - 60/*15 * 2 + 10 * 3*/) / 4
//
take = Double((item.startTime ?? 0) - Int(Date().timeIntervalSince1970)) * 1000.0
let start: Int = item.startTime ?? 0
take = Double(start - Int(Date().timeIntervalSince1970)) * 1000.0
// 1000+ms
let customViewY = view.frame.height - view.safeAreaInsets.top - view.safeAreaInsets.bottom - buttonWith - 36
let customViewY: CGFloat = view.frame.height - view.safeAreaInsets.top - view.safeAreaInsets.bottom - buttonWith - 36
/* 总结
1. 赋值时,添加值类型,在1,2,3位运算符号中都会提高编译速度
2. 函数传参,if 判断,三位运算,?? 运算 都不要有赋值运算过程,or 函数式代码
3.
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment