tl;dr:

If you’re running unit tests on an iOS project and clean building with xctool, you can enjoy significant (70% in my case) performance gains by:

  • building for active architecture only
  • not generating dSYM’s for the test build
  • experimenting with enabling Swift whole module optimisation
  • shallow clones in git

Recently I’ve been working on a rather large (see ~1000 source files, not including external libraries) iOS project. Initially written in Objective-C, the project now includes a number of Swift files.

But there were some issues.

To get a pull request from “in to green” and passing the tests on a TeamCity build server took around 15 minutes. Given I work on a large team where the codebase is committed to on a very frequent basis this was really holding us back from moving fast.

So I started taking a look at what it was that made this thing take so long.

First I noticed that we were compiling everything twice. This didn’t seem right for a debug build, so I checked the build settings of the project and saw that Build Active Architecture was set to NO for the test target. By setting this to YES you can gain around a 40% reduction in build times (note that this is set to YES for debug builds by default in Xcode, however I’ve seen many projects where it’s made its way to NO).

Next, when viewing the output of the build using xctool I noticed that we were cooking up dSYM files for the test target. By heading to the build settings for the test target and setting the Debug Information Format to DWARF I avoided generating dSYM’s which gave a ~10% speed benefit (note that again, in Xcode 7 this is set as default for new projects but I have seen many legacy projects where this is not the case).

Additionally I noticed again in xctool that the Swift file compilation was taking a rather long period of time. While whole module optimisation typically increases build times I experimented with enabling it for the test target and received an additional 10% in build and test time savings (why this is the case I am still unsure - I’ll be devoting some of my time in the following weeks for tests and will report back with any findings).

Lastly, I saw that the time spent to clone our project was pretty high. After doing some man paging ($ man git-clone for the interested) I found that git clone has a --depth argument. By specifying 1 as the depth when cloning the repo to build and test my checkout times were reduced from ~1m to ~10s. Woohoo!

If you find your build and test times are high, they might not have to be. And if you have a large team where people are often hitting a codebase with new commits then time savings are even more valuable.

Cheers!

Tom