Swift Compilation Reporting at Tumblr
Doing a clean build of the Tumblr iOS app takes…a while, and we have a bunch of developers on the team, assuming each person does at least two clean builds a day1 that adds up to, well, too much time. As we march forward with Swift for new features, we noticed our compilations times increasing at surprising rates. There have been a few blog posts outlining expressions that the Swift compiler has trouble on. For instance, type inference of nested literal expressions2 and operator overloads are expensive to resolve.
To address this, we decided to automate monitoring of compilation performance. The goal was to create a weekly job that would compile our project with specific debug flags3, process the results, and email out the slowest compilation paths.
The result is a Swift script, called SwiftCompilationPerformanceReporter
(nicknamed SwiftCPR
), that we use to generate our weekly compilation report. Below are the steps SwiftCPR
takes:
Runs a clean build with the following command4
xcodebuild -workspace workspacePath -scheme scheme clean build OTHER_SWIFT_FLAGS="-Xfrontend -debug-time-function-bodies" | grep [1-9].[0-9]ms | sort -nr > buildOutputDirectory
where
workspacePath
,scheme
, andbuildOutputDirectory
are the workspace file, scheme, and output directory for the raw compilation logs, respectively. These can be specified in theconfig.json
file.Processes the raw compilation logs and merges duplicate entires.
Sample raw logs:
5992.1ms /Users/tumblr/workspace/SwiftCPR/orangina/Classes/PerformanceLoggingEvent.swift:267:37 final get {} 5718.3ms /Users/tumblr/workspace/SwiftCPR/orangina/Classes/PerformanceLoggingEvent.swift:267:37 final get {} 4376.1ms /Users/tumblr/workspace/SwiftCPR/orangina/Classes/UniversalLink.swift:127:25 private final class func dictionaryOfAppArgumentsFromQueryString(string: String) -> [NSObject : AnyObject]? ...
Outputs a final report with the total compilation time and the slowest
limit
compilation paths, wherelimit
can be configured in theconfig.json
file.Sample report:
Total build time: 1115.24661797285 11.7104 /Users/tumblr/workspace/SwiftCPR/orangina/Classes/PerformanceLoggingEvent.swift:267:37 final get {} 8.5783 /Users/tumblr/workspace/SwiftCPR/orangina/Classes/UniversalLink.swift:127:25 private final class func dictionaryOfAppArgumentsFromQueryString(string: String) -> [NSObject : AnyObject]? ...
Once the above steps are complete, our job emails the report to the team! From these insights, we have been able to refactor functions that took over 10 seconds to compile to roughly a tenth of a second. Hope this script can help your team better profile Swift compilation times!
1: Majority of our builds are incremental.
2: This has been resolved and the fix will ship with Swift 3!
3: Specifically, -debug-time-function-bodies
4: Thanks to Michael Skiba!