Understanding & Reducing Startup Time With Instruments
Written by Team Kodeco
It’s crucial to ensure that your app starts up quickly. A slow launch can frustrate users and may even lead to your app being killed by the system watchdog process. Tools such as Xcode’s Instruments can help you investigate and reduce your app’s startup time.
Let’s consider an example where we have a AnalyticsService
that has a very long startup time in a SwiftUI app.
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
AnalyticsService.shared.longStartupTime()
return true
}
}
class AnalyticsService {
static let shared = AnalyticsService()
private init() {}
func longStartupTime() {
sleep(10)
}
}
struct ContentView: View {
var body: some View {
Text("Hello world!")
}
}
You’ll also need to update your main app file to the following:
@main
struct SwiftUI_ToolkitApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
Note your preview shouldn’t load at the moment, as the app startup time is causing it to time out.
In the above code, AnalyticsService.shared.longStartupTime()
is causing a delay in the app’s startup time due to a sleep call.
Here’s how to use Instruments to investigate:
- Run your app in the simulator or on a device.
- In Xcode, choose Profile from the Product menu or press Command-I. This will launch Instruments.
- In the template selection dialog that appears, choose App Launch. This will launch the Time Profiler Instrument.
- Click the red Record button at the top-left to start profiling your app.
- Once the app starts, you can stop the recording.
On the timeline, you can see the processes and how much time each task is taking. You can expand each process to see what methods are being called during startup and how long they take.
Here’s what the Time Profiler Instrument looks like:
You should notice that AnalyticsService.shared.longStartupTime()
is causing a significant delay in the app’s startup time. This is a clear sign that the method needs optimization.
One possible way to improve this is by deferring the call to longStartupTime()
until after the app has finished launching or performing it on a background thread. Here’s an example of how you can do this:
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
DispatchQueue.global().async {
AnalyticsService.shared.longStartupTime()
}
return true
}
}
Here’s what your preview should look like:
In the modified code, longStartupTime()
is called on a background thread, which won’t block the main thread and allows your app to start up faster.
Remember, Instruments is a powerful tool to help you diagnose and solve performance issues in your app.