paint-brush
Why you should care about your Swift compile timeby@ivanbruel
512 reads
512 reads

Why you should care about your Swift compile time

by Ivan BruelSeptember 12th, 2016
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

This is the story of how <a href="https://travis-ci.org" target="_blank">Travis-CI</a>’s <a href="https://docs.travis-ci.com/user/customizing-the-build#Build-Timeouts" target="_blank">50 minutes build timeout</a> made me care about my code’s compilation time.

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - Why you should care about your Swift compile time
Ivan Bruel HackerNoon profile picture

This is the story of how Travis-CI’s 50 minutes build timeout made me care about my code’s compilation time.

TL:DR: Install the Build Time Analizer, add this to your Podfile, fix your code, make PRs for your dependencies and spend less time compiling.

Travis CI’s struggle

Travis CI as many other CI platforms, offers a free tier for open source, but not without its limitations. In the specific case of Travis, the limitation is a 50 minutes build time out.

I understand the server costs for providing such a great tool for open source projects, but this limitation appears to exist on Travis-CI.com as well (the paid version of Travis CI).

Although this is a non-issue for testing huge frameworks such as RxSwift (with 997 tests) or ReactiveCocoa (with 1508 tests), the same cannot be said for testing/deploying actual applications with a lot of dependencies and/or a huge code base.

SwipeIt as study case

SwipeIt — Reddit with a swipe

For the past few months I’ve been developing SwipeIt as part of a benchmark into MVVM and MVC in iOS development (you can read more about this on another Medium story).

SwipeIt is a Tinder like app for Reddit where you have to either upvote or downvote a link to move on to the next the link.

For reference_, SwipeIt_ has around 10 dependencies on the unit testing target, compiles 72 .swift files (of which 16 are specs) and copies 20 bundle resources (including JSON files and HTML).

As for the actual application target, it has 28 dependencies, compiles 132 .swift files and copies 6 bundle resources.

The last (unoptimized) successful test run on Travis took 14 minutes and passed 77 tests. Out of those 14 minutes only 2.4 seconds were spent on actual testing while the rest was spent on building the required files.

In comes the deploy

This is where things get tough in terms of build time. Whereas unit testing runs on a DEBUG build setting, any deployments to Fabric, Testflight or HockeyApp should run on a RELEASE build setting. This leads to an actual 2x build time increase of both shared dependencies and code being tested.

Jack Bauer meme, circa 2004

As can be seen in Travis-CI’s build history, a test and deploy strategy was taking a little over the 50 minutes threshold.

Swift and the Build Time Analyzer

Swift has been known to have some compile time issues in regards to Type-Inference, Nil Coalescing Operator, Casts, Lazy Properties and a few others (for more information check out this awesome post and its followup) .

With the Build Time Analyzer we can easily understand which parts of our code are taking the longest to compile.

SwipeIt’s Build Time Analyzer

Although the BTA does help in debugging what I might be doing wrong, most of the compile time is actually spent on dependencies.

Adding the code above to your Podfile will make sure you can the Build Time Analyzer will also analyze your Cocoapod dependencies.

Saving the world one PR at a time

At the time I found out that most of my compile-time was spent on two popular libraries, GPUImage2 and ObjectMapper.

As can be seen on my two pull requests here and here, a lot of time can be saved by working around Swift’s compiler problems.

Although saving 1 second on ObjectMapper and 9 seconds on GPUImage2 might seem irrelevant, these metrics were obtained on the most recent Macbook Pro Retina 13-inch. Not everyone using these libraries has such a powerful laptop at their disposal and especially not CI platforms where those seconds might actually turn into minutes.

In the end, I got SwipeIt to only take 7 minutes for Testing and 33 minutes with a Test + Deploy task on Travis-CI by optimizing my code, isolating the test target and tweaking my Fastlane configs.

P.S. My clean builds are also taking a lot less :)