This article introduces concepts and best practices related to startup optimization.

What is priming

Let’s start by looking at what startup types there are and the characteristics of each.

Start type

There are three startup types: cold startup, hot startup, and restart. The following are their features.

  • Cold start
    • After the restart.
    • The APP is not in the iPhone’s memory.
    • The APP thread does not exist.
  • Warm start
    • Recently terminated.
    • The APP part is in memory.
    • The APP thread does not exist.
  • Restart the
    • The APP is paused (e.g. by pressing the home button).
    • The entire APP is in memory.
    • The APP thread exists.

After the introduction of startup types, let’s take a look at how many startup stages there are and what to avoid at each stage.

There are six stages to getting started

The six phases are System Interface initialization, Runtime initialization, UIKit initialization, Application initialization, first frame initialization, and Extended.

Let’s take a look at what happens at each stage.

  • System Interface: Initialization of the underlying System Interface, the work of the System part takes a fixed time, that is to say, the System part of this stage is not our concern.
  • Runtime Init: Initializes the language’s Runtime environment, calling the static load method for all classes.
  • UIKit Init: instantiates UIApplication and UIApplicationDelegate, starts event handling, and system integration.
  • Application Init: call UIApplicationDelegate/UISceneDelegate lifecycle callback, such as:application:willFinishLaunchingWithOptions:.
  • Initial Frame Render: Create, execute the layout and draw the view; Submit render the first frame.loadView/viewDidLoad/layoutSubviews
  • Extended: This phase is a specific time after the first frame is displayed. This phase loads data asynchronously. Your APP should be interactive and responsive during this phase.

Here are some things to avoid at each stage.

  • System Interface
    • Avoid connecting useless frameworks.
    • Avoid loading dynamic libraries at startup stage.
    • Hardlink all dependencies.
  • Runtime Init
    • Reduce calls to the +load method.
    • Use +initialize to lazily load static initializations.
    • Expose the initialization API in the framework.
  • UIKit Init
    • Reduce the work of UIApplication subclasses.
    • Reduce the work of UIApplicationDelegate initialization.
  • Application Init
    • Postponing unrelated work in the UIApplicationDelegate life cycle.
    • Resources are shared between two scenes.
  • Initial Frame Render
    • Reduce view hierarchy and lazy view loading.
    • Use high-performance automatic layout. How to write a high-performance Auto Layout
  • Extended
    • Os_signpost should be used to detect time-consuming code.

Having described the startup types and startup phases, let’s look at how to measure correctly.

Correct measurement start

During start-up time measurements, a clean and consistent measurement environment should be maintained for multiple measurements so that the results of the measurements are convincing.

You can keep the environment consistent by:

  • Restart the phone and let it sit for 2 to 3 minutes.
  • Launch flight mode or mock environment.
  • Do not use an iCloud account, or use a consistent iCloud account.
  • Use App release mode.
  • Measure thermal start.

We should test both new and old equipment during the measurement.

The startup time can be tested using XCTest.

How to optimize startup time

Mainly through the following three blocks to optimize.

Reduce your workload

  • Defer work not related to the first frame. Such asapplication:willFinishLaunchingWithOptions:Non-important interface calls in.
  • Removes code blocking the main layer. Time-consuming operations must be handled asynchronously by child threads.
  • Reduce memory usage.

Specify the correct priority

This section focuses on the proper use of GCD.

  • Use the correct Qos for task.
  • Use scheduler to optimize startup.
  • Use the correct primitive priority.

Optimize the code

  • Simplify existing code.
  • Use the right data structures and algorithms.
  • Cache everything that is cacheable.

conclusion

  • Optimizing startup time is important, and we need to make it part of daily development.
  • Delete all unnecessary code and resources.
  • Proper use of GCDS, data structures, and algorithms.
  • Refactoring simplifies existing code.
  • Cache as much as possible.