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 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 — 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.
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 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.
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 :)