Skip to content

Instantly share code, notes, and snippets.

@tylermilner
Created November 27, 2017 22:55
Show Gist options
  • Star 20 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save tylermilner/84d4f88b03c21ce6ec488e72505bec53 to your computer and use it in GitHub Desktop.
Save tylermilner/84d4f88b03c21ce6ec488e72505bec53 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 {
// ...
}
/// 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"]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment