Understanding the aspects of iOS App Launch Time

Ravi Aggarwal
Mar 24 · 7 min read

There are some old sayings that first impressions last or the first impression is the last impression…

And, the same is true for Mobile Applications too.

A nice launch image I got from Unsplash

Waiting for launch is the first user experience any app provides. There could be many things happening behind that launch screen of your app and of course, it should be ready for use asap. Fancy animations can only go so far to interest the user, eventually, they just want to get the thing done!

And, since an app can be launched n times in a day, it is important to care about this metric. All the time elapsed between the user tapping your app icon and the first View being drawn on the screen contributes towards the perceived launch time of your app.

Before we talk about the factors that contribute towards the launch time, let’s see the various types of launches.

Types of launch sequences

  1. Cold Launch — This means that the App process doesn’t exist in the system’s kernel buffer cache. This generally happens when the app is launched for the first time or when the device has been rebooted and the kernel cache has been cleared. This kind of launch takes the maximum time and hence should be considered for launch time analysis.
  2. Warm Launch — This is the type of launch where the application process and data exist in the system’s memory and is then brought into the foreground. This is similar to killing the app and relaunch.
  3. Hot Launch — This launch happens when the app is brought to the foreground from the background or suspended state.

Now, that we know about the launch sequences, we need to talk about the two categories of launch times.

Pre-main() time

This is the time utilized by the kernel to load your Application (Mach-O Executable). You can read more about the loading sequence here.

All the time taken until the control reaches your app’s main() function is counted towards pre-main time.

And, since all this happens before the control reaches your app, this time is difficult to control. Well, not really, but we’ll talk about that.

Dyld has a built-in mechanism to measure this, all you have to do is edit your app scheme and add an environment variable DYLD_PRINT_STATISTICS as 1 , as can be seen below

You can also set the build configuration to Release mode and it would be better to run this on an iPhone instead of the simulator. Once the configuration is done and you run the app, you’ll see something like this printed in the console.

Pre-main launch metrics in console

There are multiple factors affecting the launch times like dylib loading time, rebase/binding time, etc. and we’ll discuss them in some time.

First, we need to look into the second category of launch time.

Post-main() launch time

This is the time taken from the start your app’s application:willFinishLaunchingWithOptions: and application:didFinishLaunchingWithOptions of your AppDelegate all the way up to the first ViewControllers drawing cycle end i.e. until viewDidLoad and viewDidLayoutSubviews are called.

As you might have guessed, to measure this time you’ll have to measure the time from willFinishLaunching method to the viewDidLayoutSubviews of the first ViewController, which in general is the Walkthrough/Home Screen of your app.

And, we’ll discuss the things affecting this launch time too.

So the final equation for total launch time is

pre-main() time + post-main() time = Total launch time of App

Now, let’s talk about the most anticipated part of this article

Factors that affect the launch time performance

There are several factors that affect your launch time performance

Dynamic Library Load Time

The dynamic loader (dyld) loads the app’s executable file and examines the load commands in the executable to find frameworks and dynamic libraries that the app needs. Any dynamic framework added to your app contributes towards this time.

Hence, limiting the number of frameworks you embed in the “Linked Frameworks and Libraries” setting of Xcode can help in reducing launch time.

You can read more about the dyld here.

Another solution to this is to use static frameworks, they are built into the app executable at compile-time, hence dylib doesn’t have to do all the above work.

By just doing this, you can save a ton of pre-main() launch time.

Pre-main() time with static frameworks
Pre-main() time with dynamic frameworks

Although, with iOS 13, dyld3 is included in iOS apps and this is a big improvement as this will make the iOS apps launch 2x faster. But, it is still no match for using static frameworks.

Static Initializers

Certain code in your app must run before iOS run your app’s main() function, adding to the launch time. This code includes

  • C/C++ Static Initializers — Normally, you wouldn’t find something like this in your app, but if you do, I’d love to know more about it. Any function defined as __attribute__((constructor)) is a static constructor in C, and their specialty is that they get called before your main() is executed! You can read more about it here.
  • Objective C +load methods defined in classes or categories. They are called before your main() and increases the ObjC setup time as you can see in the console image above. Also, this method is deprecated, you should use +initialize method instead.
  • Any function linked to the __DATA,__mod_init_func segment of an app executable or Mach-O. These functions are usually located inside the __DATA segment’s __mod_init_func section.

So, as a general rule of thumb, move the code to a later stage of the app’s life cycle, after the app has finished launching but before the results of the work are needed.

You can use the Static initializer instrument in Xcode to find out how much time does your app spends running static initializers.

If you would like to read more about the process that happens before your main() executes, please read this article.

UIKit Lifecycle Methods

UIKit initializes an instance of your app delegate class and sends it the application(_:willFinishLaunchingWithOptions:) and application(_:didFinishLaunchingWithOptions:) messages.

These methods are called on the main thread and since the time spent to execute them is counted towards launch time, it is advisable to only create the app’s initial display here and defer other tasks.

If it makes sense to show stale data to the user, defer data model synchronization or API calls until the app is running. Initialize non-view functionality, such as persistent storage and location services, on first use rather than on app launch.

Drawing Initial View Hierarchy

The time required to draw the views that are required on the first frame of the app is also counted towards the launch time. In UIKit every view is added to the view hierarchy on the main thread and thus more complicated view hierarchy leads to higher launch time.

Reducing the complexity of the view hierarchy and replacing the views that override draw method with regular UIView will help in improving the load time.

Try rendering only the parts of view that are visible on the screen.


There could be many other reasons which can contribute to the launch time, but these are the main ones I could find, and, I believe if you religiously follow the above approaches, you’ll create a better experience for your users.


Summary

  1. There are three types of launch sequences viz. Cold, Warm and Hot.
  2. Launch time is divided into two categories:
    Pre-main Time taken before main() executes
    Post-main — Time taken after main() execution till the first ViewController is visible.
  3. We looked at several factors that contribute to the increased launch times: dynamic library loading time, static initializers, the time taken to execute AppDelegate lifecycle methods and the time taken to draw the first ViewController.
  4. We found out that you should really read this article to know more about the pre-main() process. 😛

Tokopedia Engineering

Story from people who build Tokopedia

Thanks to Meet Gupta

Ravi Aggarwal

Written by

iOS developer, blogger, sketcher? and a ukulele player who is planning to travel the world. Contact me on ravi.aggarwal61@gmail.com

Tokopedia Engineering

Story from people who build Tokopedia

More From Medium

More from Tokopedia Engineering

More from Tokopedia Engineering

Deciphering the Art of Estimation

More from Tokopedia Engineering

More from Tokopedia Engineering

Backpressure in Reactive Streams

More from Tokopedia Engineering

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade