preface

This paper will start with a simple exploration of APP startup optimization, and first introduce the basic concepts related to startup.

One: virtual memory & physical memory

In the physical memory era, memory addresses are physical addresses, and data access is directly through physical memory addresses. There are two problems with this approach:

  1. The memory is not enough.

  2. Memory data is not secure.

In view of the above problems, scientists put forward the idea of virtual memory, and through the mapping table of the corresponding relationship between virtual address and physical address let the idea of virtual memory really ground. The total size of the application, data, and stack is limited by the size of the physical memory. Each process has its own independent virtual memory, which cannot be accessed by each other, thus ensuring data security between processes.

  • Each process has its own independent virtual memory, iOS currently each process virtual memory size is 4G, 32-bit system addressing space from 0x00000000 to 0xFFFFFFFF (4G), 64-bit system to be compatible with 32-bit, so the first 4G space reserved. The addressing space ranges from 0x100000000 to 0xFFFFFFFFFFFF (8G). Virtual memory is managed by page (page capacity, ARM64 16K, X86_64 4K).

  • Through selection, the operating system decides to save the active content of each process at any time in physical memory to avoid wasting physical memory.

  • When accessing Memory data, the program always accesses its own virtual Memory, and then maps virtual addresses to physical addresses through the Memory Management Unit (MMU). If found in the Page table to access the Page is not in memory, are produced by Page Fault anomalies (Page Fault, or missing pages interruption), the current process will be blocked, if the operating system with free Page in physical memory, it will need to access the Page load memory, if not, it USES the Page replacement algorithm with the need to access the Page replace the less active Page.

Mapping between virtual memory and physical memory:

2:ASLR

The above virtual memory solves the problem of data security between processes, but since the starting address and size of virtual memory for each process are fixed, this leads to our data is very easy to crack, and the corresponding data security does not exist. To address this issue, Apple introduced ASLR in iOS4.3.

  • ASLR:Address Space Layout randomization, is a kind of targetBuffer overflowtheSafety protection technologyBy randomizing the layout of linear areas such as heap, stack and shared library mapping, it increases the difficulty for the attacker to predict the destination address, and prevents the attacker from locating the attack code directly, so as to prevent overflow attacks.

The purpose is to configure some sensitive data (such as APP login and registration, payment related code) to an address that the malicious program cannot know in advance, making it difficult for attackers to attack by randomly configuring the data address space.

Due to the existence of ASLR, the loading addresses of executable files and dynamic linked libraries in virtual memory are not fixed every time they are started up. Therefore, resource Pointers in the image need to be repaired to point to the correct address during startup. That is, the correct memory address = ASLR address + offset.

Three: start classification

Start generally refers to the process of starting from the user clicks on the app icon to application: didFinishLaunchingWithOptions: method execution is finished, according to different scenarios, the boot can be divided into two kinds: cold start and hot start.

  • Cold start: The system does not cache any process information. Typically, the APP is launched directly after the phone is restarted.

  • Hot start: If you kill the APP process and immediately restart it, it is a hot start because the process cache is still there.

According to the above classification, it is the cold start that needs to be optimized.

Four: start-up stage

IOS APP startup is divided into two stages with main function as the separation point:

  • T1: before main, that is, pre-main. The operating system loads the App executable into memory and performs a series of loading & binding tasks, which is simply the DYLD loading process.

  • T2: the stage after main. That is, starting from the main function, to the application: didFinishLaunchingWithOptions: method execution is finished, the main is to build the first interface, and complete the rendering.

Five: optimization plan

5.1: pre-mainPhase optimization scheme

The time spent in the pre-main stage is actually the time spent in the dyLD loading process. The loading process of DYLD has been analyzed in the dyLD application loading of the underlying principles of iOS.

Add the Environment variable DYLD_PRINT_STATISTICS to the Edit Scheme -> Run -> Arguments -> Environment Variables:

When you run the test project, you see the following output (empty project, so less time consuming) :

  • Dylib Loading Time: dynamic library loading time.

    • Optimization: Apple’s dynamic libraries have all been loaded into the shared cache for high-speed optimization. The developer’s own dynamic library is recommended by Apple not to exceed6If the number exceeds the recommended multiple dynamic library merge.
  • Rebase/Binding time: relocation (offset correction) /binding time.

    • Rebase: Any app-generated binary has an address for all code (methods, functions, etc.) inside the binary. This address is the offset address in the current binary. When the APP starts, the system randomly assigns an ASLR (Address Space Layout Randomization) Address value each time (a security mechanism that randomly assigns a value and inserts it into the beginning of the binary). For example, if you have a test method in the binary with an offset of 0x0008 and a randomly assigned ASLR of 0x1EA0, the real memory address of the test method at runtime is ASLR + offset (i.e. 0x0008 + 0x1EA0 = 0x1Ea8).

    • Binding: For example, the printf external function, described in LLVM & Clang2.1, creates a corresponding symbol in the mach-o file generated at compile time, and then binds the real address of the external function to the symbol when called at run time (i.e. dynamic symbol binding). In a word: binding is the process of assigning values to symbols.

      • Optimization scheme: None.
  • ObjC Setup Time: time required for OC class registration.

    • Optimization: Remove obsolete class files and methods from the project. If it isSwift, use as much as possiblestruct.
  • Initializer Time: Time required for executing the +load method and constructor.

    • Optimization: Try not to implement it yourself+loadMethods and+initializeMethods. Do not perform time-consuming operations in these methods or put time-consuming operations into child threads if they must be implemented.

5.2: mainOptimization of the stage after the function

Most of the optimization in the pre-main stage solves the problem of resource waste and can only achieve the optimization effect of milliseconds. What is most obvious to the user at startup, and what really needs to be done, is mostly the optimization of the business logic after main.

In the application: didFinishLaunchingWithOptions: the main business is divided into three types:

  • Initializing a Third PartySDK.
  • APPRun environment configuration, tool class initialization, etc.
  • Home page presentation logic, etc.

Optimizations after main:

  • Reduce the process of initiating initialization. Lazy loading can be lazy loading, can delay delay, can put in the background initialization put in the background, try not to occupy the main thread startup time.

  • Optimize the code logic, eliminate unnecessary code logic, reduce the elapsed time of each process.

  • Start stage can use multithreading to initialize, use multithreading, the CPU performance to maximize.

  • Try to use pure code to build the UI framework, especially the main UI framework, such as UITabBarController. Try to avoid using XIBs or SB, which are more time consuming than pure code.

  • Use fake data or caching to render the first page quickly.

conclusion

This is a brief introduction to the probabilities and optimizations associated with startup, followed by a brief exploration of binary rearrangement in the pre-main phase.