Created
November 27, 2017 22:55
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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