Fresh apps are usually able to startup in the time it takes for backboardd to animate from the icon to your first controller. But over the lifetime of an app, you can build up technical debt and slow things down.
One of the biggest offenders to slow startup, and slowness in general, is disk I/O. Even worse, doing I/O on the main thread.
With apps that have been around for a while, it can be daunting to be given a task to "make it faster". Here's a neat debugging tip I found that logs app-wide disk I/O and can help get you started.
Start by adding a symbolic breakpoint in Xcode. Do this before running your app.
In the Symbol field add
-[NSData initWithContentsOfFile:]. This method is used by a lot of the disk I/O APIs that iOS developers end up using, so it should catch most of what you need.
You will want to print the first parameter of the method -initWithContentsOfFile:, the string
path. Since this method is part of Foundation and already compiled, you can't just drop a breakpoint in the implementation.
Instead, you just need to print the first argument. You can find the parameter in the registers. The first two are
_cmd, so you just need to print
$esp+12 for 32 bit architectures or
$rdx for 64 bit.
Add a Debugger Command action with the following command:
// 32 bit: po *(int*)($esp+12) // 64 bit po $rdx
In addition to the file path, it would also be great if we knew what thread the file was being accessed on. To do this, add another Debugger Command action with
You'll probably want to setup another symbolic breakpoint identical to the previous one except using the symbol:
Oddly enough this isn't the designated initializer, so you can't capture everything with just
Try running your app. If you're running on an iOS 8 device or simulator, you should see a bunch of output when the app launches.
Using a small hobby app and some regex to cleanup my logs, I get the following:
Library/Application Support/iPhone Simulator/com.apple.iphonesimulator/extended_display.plist thread #1 // what's this?? Documents/latest.feed thread #1 System/Library/TextInput/TextInput_dictation.bundle/Info.plist thread #1 System/Library/TextInput/TextInput_en.bundle/Info.plist thread #1 System/Library/TextInput/TextInput_emoji.bundle/Info.plist thread #1 System/Library/KeyboardLayouts/USBKeyboardLayouts.bundle/USBKeyboardLayouts.plist thread #1 Library/ConfigurationProfiles/PublicInfo/MCMeta.plist thread #1 System/Library/CoreServices/SystemVersion.plist thread #1 Library/ConfigurationProfiles/EffectiveUserSettings.plist thread #1
There is a lot of system disk I/O happening, and unfortunately all on the main thread. That's pretty much out of my control.
However, I can see that I'm reading the file Documents/latest.feed from the main thread (that's thread #1)! That's enough to give me a clue to track down where that file is read and maybe toss it off to a background queue.
If you want more detail, you could replace the
thread info action with
bt to print out a backtrace at each disk I/O event. That will output a ton of logs that you can then sift through.
Hopefully this post helps track down pesky I/O issues. Happy hunting!Tweet