When we released our first application, True Weight, it had memory issues.
As soon as our customers reported problems we started working to find the cause. We stripped the application down piece by piece until we found the problem, a single line of code that enabled a button was triggering a bug in the iPhone OS. The bug caused an OS level memory leak that eventually required a device restart to fix. Not a good first impression.
We reported the bug to Apple, worked round the issue, and released a new version, but the damage was done. The poor feedback we received in some of our early reviews still remains on the App Store and has undoubtedly effected sales in some countries ever since.
When we started development on our second application, Connected, we were determined that we wouldn’t repeat the problems that we had with True Weight. We got in touch with Apple developer support to find out if there was anything else we could have done to spot this bug before shipping. The advice came back... “For memory issues like this, there really aren't any tools that you can use to debug them - they simply should not happen”. Maybe we were just unlucky.
A few weeks later we came across a post by Landon Fuller that described a technique for determining available memory on the iPhone. This looked like just what we’d been searching for. So after finishing core development on Connected it was time to start hunting for memory leaks and tuning performance...
Step 1: Testing with Instruments in the simulator. We started testing by using Instruments in the simulator. We found a small number of leaks which were easy to fix due to the high quality of feedback Instruments provides. We also noticed that the total memory footprint reported by Instruments was quite high. This turned out to be due to a technique we were using to create a smooth animation between puzzles. After some adjustments we had reduced the memory footprint by 90% and were pretty happy with our efforts.
Step 2: Testing with Instruments on the device. As advised by Apple there is no substitute for actually testing on the device, so the next step was to test with Instruments on some real hardware. We were surprised to see that the memory footprint reductions we’d seen in the simulator were not as good on the device. In the end we couldn’t improve the memory footprint further and had to settle for a 50% overall improvement, but it was a clear illustration that there are real differences between the results that are reported in the simulator and on the device.
Step 3: Live memory testing on the device. This was the point at which we shipped True Weight, so in order to avoid a repeat performance we knew we needed to go further. Using the sample code from Landon’s post we created a small helper object that would write the live memory statistics to the Xcode console every few seconds. The next step was to add some automation code to the application that mimicked a users actions in an endless loop. This meant we could leave the application running for a long time and distinguish any real issues from normal short term memory fluctuations.
After leaving the test running for an hour we were surprised to see a definite memory leak. So we rolled up our sleeves and started stripping the application down until we found the cause. Surprisingly this time the problem wasn’t an obscure OS bug, it was a straight forward coding error, we hadn’t released a UIButton. This is the kind of leak you would expect to be picked up by Instruments but obviously Instruments can’t catch 100% of leaks, either in the simulator, or on the device.
After fixing the final leak and repeating the test on all versions of the iPhone OS we felt confident to ship Connected. One month later, Connected and Connected Lite have been downloaded over 10,000 times and to date we haven’t received any reports of problems, or received any crash reports in iTunes Connect.
Connected Lite on the App Store
Essential iPhone Memory Testing
28 June 2009
©2009 made-up software, all rights reserved.