Improve build times in Swift with Xcode

Drinking a glass of water, glancing at the Xcode activity view as it was building a project, I saw that until the build completes, I can have another drink. Falling into such mind state came realization of measuring time in number of drinks per compilation… or being smarter than that.

Team leader and the team can eyeball the build times per commit: for one thing to prevent loss of productivity; for another, to discover overhead from dependencies. Build slowness brings many problems in its wake.

The first thing to consider is loss of productivity. Speaking with my colleagues, it is difficult not to get the impression that most software developers expect the compiler to return with feedback fast. Given the fact that with the subsequent builds seconds add up to minutes, is is not surprising that sluggishness can derail focus, thoughts and workflow, touching in particular Continuous Integration and Test Driven Development.

Developers practicing continuous integration merge their changes back to the main branch as often as possible. System validates developer’s changes by creating a build and running automated tests against the build. In similar vein, Test Driven Development, based on running many repeated tests often under one minute, requires building a project before each test.

The second thing to consider is overhead from dependencies. Project growth entails introducing new dependencies and increases building time. Drawing experience from Big O Notation one can assess linear increase as normal, quasi-linear as drawing attention, and exponential as horrible, requiring addressing.

Put bluntly, as tracking build time indicator can protect team morale from suffering, it deserves due attention.

Impelment

Profile

Xcode aids finding code that lags the compiler. In project Build Settings under Swift-Compiler - Custom Flags, Other Swift Flags add:

The team can adjust the 400 argument with what suits project best. If compiler exceeds the specified millisecond limit, Xcode will raise warning and show the offending place.

Improve

  • Using explicit types for complex properties saves the time for the compiler and your colleagues to figure out the type.
  • Provide types in complex closures.
  • Avoid + when concatenating strings.
  • Precompute. Avoid computations directly in the if-else conditions.
  • Dependencies determine what areas of code the system builds. Dependencies within a module are per-file. Dependencies across targets are for the entire target.
  • Incremental Builds are file-based. Unrelated changes outside function bodies can result in rebuilding. As changes in function bodies do not affect the file’s interface, modifying function bodies will not recompile other files.
  • Limit your Objective-C/Swift interface. Keep your generated header minimal. Use private when possible:
    • Make IBOutlet private and IBAction private.
    • Make methods exposed to Objective-C @objc private. Or switch to block based APIs.

References

Comment Rules: The goal is to become better at our jobs. To post code, insert it between the tags <code></code> Critical is fine, but if you’re rude, I'll delete your stuff. Please do not put your URL in the comment text and please use your PERSONAL name or initials and not your business name, as the latter comes off like spam. Have fun and thanks for adding value to the converstaion!

Leave a Reply

Your email address will not be published. Required fields are marked *