February 10, 2014

How to reduce Xcode and AppCode build times

DerivedData

Both Xcode and AppCode intensively cache temporary “information” on the file system. Each time you cleanup the project, make a new build, or launch the app in iOS Simulator, IDE will read and write megabytes of files into the special folder named DerivedData. You will be surprized how much space can be freed up by executing rm -rf ~/Library/Developer/Xcode/DerivedData/* in Terminal. This command is totally safe, because Xcode will regenerate everything it needs from scratch when you build the next project.

As result of this caching, the speed of building and launching the app in debugger may significantly depend on the “speed” of your hard drive. With SSD, a typical iOS-project with precompiled information will launch in 5-10 seconds. With HDD, it will take more time. Anyway, you should know that there is an easy way to build and launch the app in iOS Simulator much faster.

Free Solution

I found this solution in the Krzysztof ZabÅ‚ocki’s talk about iOS Developer Tools. The last paragraph of the article (it is not mentioned in the video) is about the command line tool named RamDisk:

This script will let you create ramdisk for iOS sim, derived data a few other important folders. This can make your development wayyy faster.

In other words, OS X allows you to create a super-fast file storage directly in RAM and hard-link it into the file system in place of the DerivedData folder used by Xcode. You can even create multiple “virtual” drives and mount them to Application Support/iPhone Simulator and Application Support/Caches/appCode2.0 to make these caches fast and truly temporary.

There is a great blog post explaining this in more details, and some are worth quotation:

Mounting a volume on top of your existing DerivedData hides the old files. They continue to take up space, but are unreachable until you unmount the RAM disk.

The contents of the RAM disk disappear when you reboot or eject it from the Finder. Xcode will need to rebuild its indexes and all of your project’s intermediate files the next time you create one.

One more thing: such RAM disks are not “allocated” in the memory, they take only as much space as needed to keep all files.

Update → AppCode does not recommend moving the whole Caches/appCode20 folder on a RAM disk, because among everything it stores indices and local history's data. Once the in-memory storage is reset, no local history will be available. However:

DerivedData can be safely moved to a ram disk; though for big projects the full rebuild may cost more than the saved time.

Paid Solution

Unfortunately, the original Gist does not support commands stop and start, so you will have to restart OS X in order to remove RAM disks. It is not very convenient to support them between launches and you can forget to reclaim the RAM after you finish the coding session.

Fortunately, “there is an app for that”. iRamDisk will create and manage RAM disks for you. There is a standard setup for Xcode development, and you can easily mount the caches folder used by AppCode too. Here is my setup:

AppCode RAM Settings in iRamDisk

Update → iRamDisk menu bar icon stands out of the croud, so I made a replacement. Put these images in /Applications/iRamDisk.app/Contents/Library/LoginItems/iRamDisk-Helper.app/Contents/Resources and toggle the preference Show in menu bar to update.

Does it work?

YES.

I tried this on my MacBook Pro with Retina Display 8 GB and iOS Simulator launch time reduced to the matter of seconds. There is also a conversation in Twitter that you may find interesting.

It seems like the iOS Simulator launch time does not change significantly for AppCode, but I find it fascinating that SSD is not touched during massive cache readings and writings.

P.S. I assume the same recipe would work with Photoshop or Illustrator.

7 comments:

  1. I used a RAM disk for my DerivedData folder for over a year. There's definitely a performance advantage. However, I found that the folder frequently outgrows the size of the RAM disk. Xcode doesn't deal nicely with such disk full errors. So you don't see at first sight that the full RAM disk caused the build to fail. Then, the process to clean the DerivedData folder is not really straight forward. I found it only works reliably if I restarted Xcode.

    All these issues made me go back to the standard SSD based build process and overall it works better for me. Of course YMMV!

    ReplyDelete
  2. The talk of a performance boost surprises me. It would be interesting to analyse why the filesystem cache isn't preventing the disk I/O apart from the regular flushes and the initial read.

    ReplyDelete
  3. I used to use a ramdisk to record audio, in the days of OS8. Much faster than the standard 5400 rpm drives available.
    Yeah you had to get used to saving out to real disk at the end of the session, but that was OK

    ReplyDelete
  4. This is great, thanks for sharing.

    ReplyDelete
  5. I followed the instructions from this article: http://lightyearsoftware.com/2012/08/use-a-ram-disk-for-deriveddata/ and I could eject the RAM disks w/o rebooting. In case you need batch rebooting, just use DiskUtil, where all of them sit. Cmd-select the disks and click Eject from the context menu. I don't see any good reason to buy iRamDisk. Also for the reason I couldn't see any significant boost on a Fusion Drive. Everything is already as fast as it can be, disk operations are certainly not a bottleneck. Yes, I could save 20 sec on a clean build, but that's a relatively rare operation. Usual edit-compile-run flow gave me no gain. That is not to blame the author, maybe just to prepare the reader. It's not like you hit a key and the app is launched. On some configurations there can be an improvement though.

    ReplyDelete
  6. Nice, accurate and to the point. Not everyone can provide information with proper flow. Good post. I followed the instructions from this article and it really work thanks for sharing such information.

    ReplyDelete
  7. Agree with Aliaksei N. Just tested this - if improvement is there its very small. Tested on two projects timing by hand and the stopwatch error was more than the difference in speed.

    ReplyDelete