It’s never been easier to get into iOS development than it is today. The tools are largely free, and there is a plethora of quality educational content available online, including some from Apple itself. As anyone who has done iOS for a long time will tell you, there is a magical feeling of starting a new project and quickly creating something from scratch.
However, as the size of a codebase increases and the number of contributing developers multiplies, that feeling of rapid progress can degrade into a slow trudge. Software development is a very iterative process, so the amount of time between making a small code change and being able to test/experience that change is very important to overall developer productivity. At DoorDash, we’ve been working to minimize this latency, keeping our development fast and our engineers happy.
We’ll talk about a few of the approaches we’re taking to increase development velocity, but the first one is also the easiest: buy your iOS engineers new M1 Max Macbook Pros!!
New M1 MacBooks make everything faster
Apple released the consumer-grade M1 chips in the Mac Mini and MacBook Air in late 2020 (with impressive performance), and was widely rumored to be releasing the new MacBook Pros soon after. We wanted to get ahead of the game, so we started to make a business case for upgrading our entire iOS team to these new laptops as soon as possible.
From a business standpoint, the math is straightforward: An investment in developer productivity has a “payback period”. It’s simply a function of the expected time savings and the engineering cost. Instead of recovering the investment in dollars, it can be recovered in engineering time that would have been otherwise lost. In our case, that required estimating how much time these new laptops would likely save the average engineer each day and multiplying out appropriately.
Based on rough usage patterns, we assumed an average iOS engineer does around five clean builds and 30 incremental builds each day... We multiply that by our average build times to get a sense for how much time each engineer spends “waiting for the compiler” each day. A certain xkcd comic comes to mind.
Similarly, we needed to measure how much faster the new laptops are, to calculate time saved. Doing this in advance of the hardware being available, we had to do some guesstimates based off of the consumer-grade chips as well as Apple’s marketing information—with a bit of a haircut applied.
In our case, we were able to estimate that upgrading an iOS engineer would result in about 35 minutes of “saved time” each and every day. Multiplying that by the average cost of employing an iOS engineer, we found a “payback period” of less than two months!
Importantly, this rough napkin math was so overwhelmingly positive that we didn’t need to account for a bunch of the less-obvious or harder-to-measure advantages from these faster machines. For example, we didn’t quantitatively take into account how engineers would be less frustrated, how Xcode would be more responsive, that auto-complete would work faster, or that there would be reduced context-switching while waiting for compile times.
With a solid business case, we placed an order to upgrade all current and upcoming iOS engineers to a 16-inch MacBook Pro with M1 Max and 64 GB RAM.
Subscribe for weekly updates
What are the actual results?
Fast forward a couple of months, and we’ve finally got our first shipment of these new machines. We wasted no time setting up a side-by-side build speed comparison between the new and old laptops and eagerly awaited the results.
we made in our pitch. All told, our benchmark build went from 7:46 min. to 3:48 min. That’s almost twice as fast!
Twice. As. Fast.
We found that to be especially impressive. If you think through what other changes you might make to a large codebase to speed it up by the same percentage — a bunch of micro optimizations that can be done here, some obsolete code to be removed there, etc.— you would not see anywhere near the same relative speedup, even with months of work.
However, not everything is good news. With the strong demand for these laptops and the ongoing global supply chain issues, we have yet to receive the replacement laptops for all of our engineers—but they’re en route.
How else to speed up compile times?
Even with all this extra horsepower, it still takes minutes for the average build to complete. Not terrible, but not exactly the rapid iteration we’re aiming for. And as our team and codebase continues to grow, our time spent compiling will continue to increase — probably faster than Apple can decrease it with faster laptops. So what else can we do?
We can modularize our codebase. Instead of having to compile a million lines of code, we break the app down into many smaller chunks of code, mapping out the dependencies between them. Individual engineers and teams can then work on subsets of the codebase, dramatically improving development iteration speed. This is still a work in progress for us, but we’re starting to see some of the benefits and will have more to say about it in the future.
In parallel with our modularization effort, we’re also adopting new technologies like SwiftUI and Xcode Previews. These technologies allow us to almost entirely remove the tweak-compile-and-run loop when developing user interfaces. Instead, we can define our preview data and “live code” the actual view’s code, getting nearly instantaneous feedback right in the Xcode canvas. While this only helps “view” development, we’ve found that to be an area where the fast iteration is especially helpful.
We hope to have more articles that go into depth on these alternative methods of speeding up our iOS development so stay tuned.
At the end of the day, if you’re doing professional development in Xcode all day, there is little doubt that upgrading to one of these new M1 MacBook Pros is a great choice. And if working in a large iOS codebase with a bunch of other passionate developers sounds interesting to you, come join us. We’ll have an M1 Max MacBook Pro waiting for you.
Great read; thank you! I’m curious, how did you manage to disable Google maps for simulator builds?
In our codebase, we’ve wrapped the actual GoogleMaps view in another class. That class has a simple `#if targetEnvironment(simulator)` check causes it to either have a real GoogleMaps view or the dummy view we use for the M1 simulator.