Summary of iOS startup

The startup time of mobile applications is an important aspect that affects user experience. The startup time of iOS is divided into cold startup and hot startup

  • Cold start: The application is not yet running, and the entire application must be loaded and built to complete the initialization
  • Hot start: The application is already running in the background (a common scenario is when the user presses the Home button) due to an event that awakens the application to the foreground
  1. Cold startup takes longer than hot startup, and the cold startup time of each application varies greatly. Therefore, there is a large space for optimization of cold startupapplicationDidFinishLaunching:withOptions:Method is used by many applications to initialize the third-party libraries they use
  2. The hot start application will be inapplicationWillEnterForeground:Method to receive an event when an application enters the foreground

Cold start

There are a lot of resource-intensive operations involved in cold startup. Here is the app startup sequence diagram given by apple’s official documentation

The startup sequence is as follows:

  • The user clicks the APP ICON
  • Call main
  • Call the UIApplicationMain function
  • Loading UI files
  • The callback willFinishLaunchingWithOptions
  • Storing UI Status
  • Complete didFinishLaunchingWithOptions callback
  • Enter the Runloop loop

Before calling the main function, the system also does a lot of operations for us, mainly the dyld dynamic linker is responsible for, the core process is as follows

  1. Program execution starts with _dyLD_star
    • Read macho file information and set the virtual address offset for redirection.
    • Call the dyld::_main method to enter the main program of the macho file
  2. Configure some environment variables
    • The environment variable is set so that we can print out more information.
    • Call getHostInfo() to get the machO header to get information about the current running schema.
  3. Instantiate the main program, the Macho executable.
  4. Load the shared cache library.
  5. Insert dynamic cache library.
  6. Link to the main program.
  7. Initialize the function.
    • NotifSingle is called after a series of initialization functions.
    • This callback is a function load_images assigned during the runtime _objc_init initialization
    • Load_images executes the call_load_methods function, which loops through the class and the load method of the class.
    • DoModInitFunctions, which internally call functions such as _ _ attribute_ (constructor), the constructor of a global C++ object.
  8. Return the entry function of the main program, and start to enter the main () function of the main program.

Total time to start PP) = t1(time before main) + T2 (time after main)

  • T1 = system dylib (dynamic link library) and App executable load time
  • After t2 = the main function into the AppDelegate class applicationDidFinishLaunching: withOptions: method performs before the end of this period of time

How do I compute T2

Because the Class load method before calling the carrying out of the main function, so we can record the start time in the load method, at the same time to monitor UIApplicationDidFinishLaunchingNotification notice, received notice when the time is presupposed as application startup time, This has the advantage of not having to hack into the business side’s main function to record the start time

static uint64_t loadTime; static uint64_t applicationRespondedTime = -1; static mach_timebase_info_data_t timebaseInfo; static inline NSTimeInterval MachTimeToSeconds(uint64_t machTime) { return ((machTime / 1e9) * timebaseInfo.numer) / timebaseInfo.denom; } @implementation XXStartupMeasurer + (void)load { loadTime = mach_absolute_time(); mach_timebase_info(&timebaseInfo); @autoreleasepool { __block id<NSObject> obs; obs = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidFinishLaunchingNotification object:nil queue:nil usingBlock:^(NSNotification *note) { dispatch_async(dispatch_get_main_queue(), ^{ applicationRespondedTime = mach_absolute_time(); NSLog(@"StartupMeasurer: it took %f seconds until the app could respond to user interaction.", MachTimeToSeconds(applicationRespondedTime - loadTime)); }); [[NSNotificationCenter defaultCenter] removeObserver:obs]; }]; }}Copy the code

Mach_absolute_time () is not affected by the system time, only by the restart and sleep behavior of the device. It is not affected by the system time. It is not affected by the restart and sleep behavior of the device