iOS Boot speed optimization

Source: Internet
Author: User

Background

July 26 We Ali data iOS side released 4.4.0 version, this version is mainly optimized performance, where the main () phase of the start time-consuming optimization results are more obvious, from the previous 0.5-0.7 seconds, reduced to the current 0.1-0.2 seconds (main () The first line of code to didfinishlaunchingwithoptions the last line of code is time consuming, and the user experience improves significantly. Here to comb the optimization of some of the experience, welcome to communicate with you.

Application initiation Process

The launch of iOS apps can be divided into pre-main and main () phases, where the system does things in turn:

1. Pre-main Stage

1.1. Load the application's executable file

1.2. Load dynamic link insecure library carrier Dyld (loader)

1.3. Dyld recursive loading application of all dependent dylib (dynamic library dynamically linked library)

2. Main () Stage

2.1. Dyld Call Main ()

2.2. Call Uiapplicationmain ()

2.3. Call Applicationwillfinishlaunching

2.4. Call Didfinishlaunchingwithoptions

Start time-consuming measurements

Before we can optimize, we should be able to measure the time-consuming phases first.

1. Pre-main Stage

For the pre-main phase, Apple provides a measurement method that sets the environment variable dyld_print_statistics to 1 in Xcode, Run, auguments.

Pre-main phase start time-consuming measurement. png

After setting up the program to run, the console will have the following output, the pre-main phase of the process of time-consuming sweeping (Apple this demo is a bit too exaggerated ...)

Pre-main phase start time-consuming measurement. png

2. Main () Stage

For the main () stage, it is primarily measured that the main () function starts execution to the end of the didfinishlaunchingwithoptions execution, and it is time to insert the code into the project. The current time is recorded with the variable StartTime in the main () function first:

123 CFAbsoluteTime StartTime;intmain(intargc, char * argv[]) {      StartTime = CFAbsoluteTimeGetCurrent();

Then declare the global variable with extern in the APPDELEGATE.M file StartTime

1 extern CFAbsoluteTime StartTime;

Finally in the didfinishlaunchingwithoptions, the current time, and the difference between the StartTime is the main () phase of the run time.

1 double launchTime = (CFAbsoluteTimeGetCurrent() - StartTime);

Optimization of the pre-main phase

To optimize the time-consuming phases of the pre-main phase, the Dyld loading process needs to be learned, and the dyld load is divided into 4 main steps according to Apple's WWDC introduction:

1. Load Dylibs

At this stage Dyld analyzes the application-dependent dylib, finds its Mach-o file, opens and reads the files and verifies its validity, then finds the code signature to register with the kernel, and finally calls segment () for each mmap of Dylib.

In general, iOS apps will load 100-400 dylibs, most of which are system libraries, and this part of the Dylib loading system has been optimized.

Therefore, the less dependent the dylib the better. In this step, the optimizations we can do are:

    1. Try not to use embedded (embedded) dylib, load embedded dylib performance overhead

    2. Consolidate existing dylib and use static libraries (archives) to reduce the number of dylib used

    3. Lazy loading dylib, but be aware that dlopen () can cause some problems, and actually lazy loading does more work

2. Rebase/bind

During the dylib loading process, the system introduced the ASLR (Address Space Layout randomization) technology and code signing for security reasons. Because of the existence of ASLR, the image (image, including executables, dylib, and bundles) is loaded at random addresses, and the address (preferred_address) pointed to by the previous pointer will have a bias (slide), dyld need to fix this deviation, To point to the correct address.

Rebase before, bind in, rebase do is to read the mirror into memory, fixed mirror internal pointer, performance consumption mainly in IO. Bind does is to query the symbol table, set a pointer to the outside of the mirror, performance consumption mainly in CPU calculation.

So, the fewer pointers, the better. In this step, the optimizations we can do are:

    1. Reduce the number of OBJC classes (Class), Method (selector), classification (category)

    2. Reduce the number of virtual functions in C + + (overhead for creating virtual function tables)

    3. Use Swift structs (internal optimizations, fewer symbols)

3. OBJC Setup

Most of the OBJC initialization work has been done in the rebase/bind phase, and this step dyld register all the declared OBJC classes, insert the classifications into the class's method list, and then examine the uniqueness of each selector.

In this step there is nothing to optimize for, rebase/bind phase optimization, this step will be less time-consuming.

4. Initializers

At this stage, Dyld begins to run the initialization function of the program, invokes the +load method of each OBJC class and classification, invokes the constructor function (with attribute ((constructor)), and creates a non-primitive type of C + + static global variable in C + +. After the initializers phase is executed, DYLD starts calling the main () function.

In this step, the optimizations we can do are:

    1. Don't do things in the +load method of the class, try to postpone these things to +initiailize

    2. Reduce the number of constructor functions and do less in constructor functions

    3. Reduce the number of static global variables for C + +

Optimization of main () stage

This phase of optimization is mainly to reduce the work in the Didfinishlaunchingwithoptions method, in the Didfinishlaunchingwithoptions method, we will create the application window, Specifies its rootviewcontroller, calling window's Makekeyandvisible method to make it visible. Due to business needs, we will initialize each of the two-party/tripartite library, set the system UI style, check whether the need to display the boot page, whether to login, whether there is a new version, etc., because of historical reasons, the code here is easy to become larger, the start time is difficult to control.

So, to meet the business needs, didfinishlaunchingwithoptions in the main thread to do the less the better. In this step, the optimizations we can do are:

    1. Comb each of the two-party/tripartite library, find the library can delay loading, do lazy loading processing, such as in the Home controller Viewdidappear method.

    2. Comb the business logic and defer execution of the logic that can delay execution. For example, check the new version, register push notifications and other logic.

    3. Avoid complex/redundant calculations.

    4. Avoid on the home controller viewdidload and Viewwillappear do too many things, these 2 methods to perform, the first page controller can be displayed, some can delay the creation of the view should do delay create/lazy loading processing.

    5. Use a better-performing API.

    6. The home controller is built in a pure code way.

Alibaba Data iOS Optimization practice

In the above cognitive guidance, Ali data iOS began to optimize, in the pre-main phase and main () phase of a series of optimizations, and achieved certain results.

1. Optimization of the pre-main phase

1.1. Troubleshoot unused dylib and remove libicucore.tbd that are no longer in use

1.2. Delete unused files & libraries, merge duplicate files (multiple duplicate categories). Remove Libraries umsocial, Pstcollectionview, Mcswipetableviewcell that are no longer in use, and remove the duplicate library mantle.

1.3. Comb the +load methods of each class, and defer the +load method in multiple classes to +initiailize.

Optimizing the pre-pre-main phase is time consuming:

Optimizing the pre-pre-main phase is time consuming. png

The Pre-main phase is time-consuming after optimization:

The Pre-main phase is time consuming after optimization. png

Test environment: Xcode8.3.3 iOS10.2 Simulator, hot start.

Note: The test found that the Pre-main phase time has a certain fluctuation, cold start when the fluctuation is greater, which is affixed to a median level.

You can see that the pre-main phase takes a certain amount of time to fall under hot start.

2. Main () phase optimization

2.1. Remove the Dispatch_after 100ms ... Check code discovery will deliberately let the boot diagram display 100ms, do not know what logic ...

2.2. Delay loading multiple two-party/Tri-party libraries. including Tbcrashreporter, TBACCSSDK, UT, Tremotedebugger, ATSDK and so on.

2.3. Defer execution of several system UI configurations and business logic. This includes registering for push, checking for new versions, updating orange configurations, and more.

2.4. Avoid unnecessary calculations. Before and after two times to get whether to display the ad map, each acquisition needs to deserialize the configuration information in orange, and then compare the start/end time in the configuration, it takes about 20ms. The current solution is to cache with a bool attribute after the first calculation, and the next direct fetch.

2.5. Deferred loading & lazy loading partial view. The Quick Password Verification page is the first page that the user sees after the start diagram disappears, and the viewdidload phase takes about 100ms due to the decoding of the image, creation & layout of multiple views. The current solution is to defer the password input box view to viewdidappear, and to lazy load the password error view, which reduces the time to about 30m.

With the time profiler analysis of instruments, the optimized start-up speed is significantly increased, and the didfinishlaunchingwithoptions takes about 75ms (iphone6s iOS10.3.3)

Startup time-consuming: Png

One of the most time-consuming is the creation & layout of the shortcut Password verification page (Papasscodeviewcontroller), followed by the judgment code for whether to display the ad page in Dtlaunchviewcontrolle. You can see that the Papasscodeviewcontroller viewdidappear time consuming 78ms, but there is no big relationship, at this time the user has seen the page, ready to verify the fingerprint/password.

Summary & Follow-up planning

1. Summary

To sum up, it seems that the startup speed optimization is a word: let the system do less during startup. Of course, we need to know what the project is doing during startup, how much impact it has on the startup speed, and then case-by-case analysis of the engineering code, which makes the system easier during startup by putting it on sub-threads, lazy loading, and lazily loading.

2. Follow-up planning

2.1. Replace part of the vast library with a more lightweight solution.

2.2. Organize the code to eliminate repetitive implementations and avoid repetitive classes & classifications & methods.

2.3. Comb and remove the classes & classifications & methods involved in a business that has been offline.

2.4. Monitor the change trend of grayscale version startup speed, Discover & solve the problem of slow startup speed early.

Resources

    • WWDC Optimizing App Startup Time

    • Attribute Summary

    • Dyld Loading Mach-o

    • Optimize your App's startup time

    • Today's Headlines iOS client startup speed optimization

iOS Boot speed optimization

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.