Introduction to the

This article mainly introduces the iOS performance optimization information from four aspects: application startup time; Page refresh scrolling fluency; Power consumption; Size of the installation package

  • Application startup time
  • Page refresh scrolling fluency
  • Power consumption
  • Size of the installation package

1 Application startup time

The application startup time here refers to the time between the application startup and the display of the first page.

There are cold startup and hot startup. Hot startup means that the application is alive in the background and then starts the application. We’re talking about cold start.

A startup time of less than 400ms is optimal because the time between clicking on the icon and launching the Launch Screen and the Launch Screen disappearing is 400ms. The startup time cannot exceed 20 seconds; otherwise, the system will kill you.

Xcode9 has an environment variable (Edit scheme -> Run -> Arguments). DYLD_PRINT_STATISTICS is set to 1. DYLD_PRINT_STATISTICS_DETAILS can be set to 1 for more detailed information.

Then start the application and you can see the following information

Total pre-main time: 5802.5 milliseconds (100.0 milliseconds) Dylib loading time: 264.36 milliseconds (44.9%) Rebase /binding time: 56.19 milliseconds (9.5%) ObjC Setup Time: 49.84 milliseconds (8.4%) Initializer time: 217.71 milliseconds (37.0%) vs intializers: 9.18 milliseconds (1.5%) libMainThreadChecker. Dylib: 36.42 milliseconds (6.1%) libglInterpose. Dylib: 82.35 milliseconds (14.0%) libMTLInterpose. Dylib: 32.51 milliseconds (5.5%) MeeYi: 24.89 milliseconds (4.2%)Copy the code

As you can see, before executing the main function, the application is prepared to execute four processes: dylib loading, rebase/ Binding, ObjC Setup, and Initializer. We will examine these processes below.

  • Load dylibs: Load dynamic libraries, including system, self-added (third-party), and recursively load dependent libraries layer by layer.
  • Rebase&Bind: Fix pointer. The internal storage logic is that information is stored in virtual memory, not directly corresponding to physical memory. When an application is started, the start address of the memory is random. Therefore, virtual memory and physical memory must be connected. For security, prevent hacker attacks.
  • Objc: Registers class information in the global Table
  • InitializersC/C++ statically initializes objects and tags__attribute__(constructor)The method of
  • Main() : Executes the Main function and executes the APPDelegate method
  • Load Window+ load RootViewController+ initialize operation: in the maindidFinishLaunchingWithOptionsPerform actions such as initializing third-party libraries, initializing basic information, loading RootViewController, and so on

After understanding the application startup process, the application startup optimization work is subdivided into the optimization of each process.

1.1 Before main() :

1.1.1 DYlibs: Load dynamic library

The first step is to load the dynamic library. Loading the system’s dynamic library is fast because it can be cached, while loading the embedded dynamic library is slower.

So the key to making this step more efficient is to reduce the number of dynamic libraries. Merge dynamic libraries.

For example, the company has set up the following dynamic libraries by private Pod: XXTableView, XXHUD, XXLabel, it is strongly recommended to merge into a XXUIKit to improve the loading speed.

1.1.2 Rebase & Bind & Objective C Runtime

Both Rebase and Bind are designed to solve the problem of pointer references. For Objective C development, most of the time is spent loading Class/Method symbols, so common optimizations are:

1) Reduce the number of Pointers in __DATA.

2) Merge categories and classes with similar functionality. Such as: UIView + Frame, UIView + AutoLayout… Merge into a single delete method and class that is useless.

3) Use Swift Structs because Swfit Structs are distributed statically.

1.1.3 Initializers

Normally, we would do method-swizzling in the +load method, but this would affect application startup time.

1) Replace load with initialize. Many students prefer to use method-Swizzling to implement AOP to do log statistics and other content, strongly recommend to change to initialize in initialize.

2) Reduce the use of Atribute ((constructor) and instead initialize it with dispatch_once etc on first access.

3) Do not create threads

4) Rewrite code with Swfit.

After the main() function:

The core idea of optimization: delay initialization as far as possible if it can be delayed, and put initialization in the background as far as possible if it cannot be delayed.

Let’s start by analyzing what happens between the time you execute main and the time you display your first screen.

  • Perform AppDelegate proxy approach, mainly didFinishLaunchingWithOptions, applicationDidBecomeActive,
  • Example Initialize the third-party SKD
  • Initialize the Window, initialize the underlying ViewController
  • Obtain data (Local DB/Network) and display it to users.

In this process we can use tools to detect

  • Once you know this process, you can use the Time Profiler tool to find specific time-consuming modules. A few points to note:
    • Analyze startup time, and generally only care about the main thread
    • Select Hide System Libraries and Invert Call Tree so we can focus on our own code
    • Detailed call stack information can be seen on the right
  • Alternatively, you can check the module runtime using C functions:

CFTimeInterval startTime = CACurrentMediaTime(); CFTimeInterval endTime = CACurrentMediaTime();Copy the code

When a time-consuming module is detected, the core idea of optimization can be followed. That is:

If the initialization can be delayed, try to delay the initialization. If the initialization cannot be delayed, try to delay the initialization in the background.

2 Page refresh scrolling fluency

Before optimizing the flow level, we need to first understand the imaging process of iOS pages.

2.1 Central Processing Unit (CPU)

Object creation and destruction, object property adjustment, layout calculation, text calculation and typesetting, image format conversion and decoding, image drawing (Core Graphics)

2.2 Graphics Processing Unit (GPU) :

Texture rendering

2.3 Imaging process:

CPU calculation information, GPU rendering information into the frame cache (iOS is a dual-cache mechanism, there is a frame cache, after the frame cache), the video controller from the frame cache to display the information on the screen.

2.4 Causes of stacken:

According to the brush rate of 60FPS, there will be a VSync signal every 16ms. When the VSync signal comes, it needs to fetch the cache from the frame cache and display it on the screen. If the CPU and GPU fail to render the information to the cache every time the VSync signal comes, the display will be retrieved from the cache. You lose frames, and if you lose too many frames, you get stuck.

2.5 Detection of lag

The “lag” usually refers to time-consuming operations performed on the main thread. There are two schemes detected here:

  • The coreAnimation tool in Instruments looks at the framerate, ideally up to 60fps
  • You can add an Observer to the main RunLoop to monitor the time it takes for the RunLoop state to change. This can be done with third-party frameworks (many on Github) such as LXDAppFluecyMonitor and JPFPSStatus

2.6 Solve the problem

Minimize CPU and GPU resource consumption

2.6.1 optimization

  • Optimization of the CPU
    • Try to use lightweight objects, such as CALayer instead of UIView, for places that don’t handle events
    • Don’t make frequent calls to UIView properties such as frame, bounds, Transform, etc., and minimize unnecessary changes
    • Try to calculate the layout in advance, adjust the corresponding attributes at one time if necessary, do not modify the attributes more than once
    • Autolayout consumes more CPU resources than setting the frame directly
    • The image size should be exactly the same as the UIImageView size
    • Control the maximum number of concurrent threads
    • Try to put time-consuming operations into child threads: text processing (sizing, drawing); Image processing (decoding, rendering)
  • To optimize the GPU

    • Try to avoid the display of a large number of pictures in a short period of time, as far as possible to display a composite of multiple pictures
    • Minimize the number of views and levels
    • Reduce transparent views (alpha<1) and set Opaque to YES for opaque views
    • Try to avoid off-screen rendering
  • Avoid off-screen rendering

In OpenGL, the GPU has two rendering modes:

    • On-screen Rendering: renders On the current Screen, Rendering On the Screen buffer currently used for display;
    • Off-screen Rendering: Creates a new buffer outside the current Screen buffer for Rendering
    • Off-screen rendering is a performance drain
      • A new buffer needs to be created
      • In the whole process of off-screen rendering, the context needs to be changed several times, first from the current Screen (on-screen) to off-screen (off-screen); When the off-screen rendering is finished, the rendering results of the off-screen buffer are displayed on the screen, and the context needs to be switched from off-screen to the current screen
    • Off-screen rendering can result in:
      • ShouldRasterize = YES
      • Mask the layer mask
      • Layer. masksToBounds = YES and layer.cornerRadius >
      • Shadow, layer.shadowXXX, if layer.shadowPath is set it will not render off-screen

3 power consumption

3.1 Main sources of application power consumption are:

  • CPU Processing
  • Networks and Networking
  • Location, Location
  • Images, Graphics

3.2 Power consumption optimization:

  • Minimize CPU and GPU power consumption
  • Use less timer
  • Optimize I/O operations
    • Do not write small data frequently. It is better to write data in batches at a time
    • Consider dispatch_io for reading and writing large amounts of important data, which provides an API for asynchronously operating file I/O based on GCD. The system optimizes disk access with dispatch_io
    • For large amounts of data, it is recommended to use databases (such as SQLite and CoreData).
  • Network optimization
    • Reduce and compress network data
    • If the result of multiple requests is the same, try to use caching
    • Use breakpoint continuation, otherwise the same content may be transmitted multiple times when the network is unstable
    • Do not attempt to perform network requests when the network is unavailable
    • Allows users to cancel long-running or slow network operations and set appropriate timeouts
    • For example, when downloading video streams, instead of sending small packets, download the entire file directly or in large chunks. If you download ads, download several at a time and display them slowly. If you download emails, download several at a time, not one by one
  • Location optimization
    • If you just need to quickly determine the user’s location, it’s best to use the requestLocation method of CLLocationManager. After the locating is complete, the locating hardware is automatically powered off
    • If it’s not a navigation app, try not to update your location in real time and turn off location services when you’re done
    • Try to reduce the positioning accuracy, such as try not to use the highest accuracy kCLLocationAccuracyBest
    • Need background position, try to set up pausesLocationUpdatesAutomatically to YES, if the user is unlikely to move the system will automatically suspended position update
    • Try not to use startMonitoringSignificantLocationChanges, priority startMonitoringForRegion:
  • Hardware detection optimization
    • When the user moves, shakes or tilts the device, motion events are generated, which are detected by hardware such as accelerometers, gyroscopes and magnetometers. These hardware should be turned off when testing is not required

4 Thin the installation package

Installation packages (IPA) are mainly composed of executable files and resources, so the iOS installation package will be streamlined from these two aspects

4.1 Resources (Pictures, Audio and Video)

  • Take lossless compression
  • Remove unused resources

4.2 Thin executable files

  • Compiler optimization
    • Strip Linked Product, Make Strings read-only, Symbols Hidden by Default set to YES
    • Disable exception support, Enable C++ Exceptions, Enable Objective-C Exceptions set to NO, Other C Flags add -fno-exceptions
  • Detect unused Code using AppCode (www.jetbrains.com/objc/) : menu bar -> Code -> Inspect Code
  • Write the LLVM plug-in to detect duplicate code, uncalled code
  • Generate a LinkMap file, you can view the specific composition of executable files, which files are larger
    • You can use third-party tools to parse LinkMap files: github.com/huanxsd/Lin…

4.3 bitcode

Xcode7 has added a setting like this, which is turned on by default. After turning on the Bitcode Settings, the compiled package is not the final binary package but the bitcode intermediate code. Apple will optimize the bitcode according to the compiler and application device to give you the final, most optimized binary application package. This avoids the issue of Submitting an app package to the Appstore when Apple updates the compiler or hardware device. Also enjoy the benefits of compiler improvements.

The catch is that some third-party libraries don’t support Bitcode, so you have to turn it off if you want to use the corresponding third-party library. Due to a long time, I have forgotten which third party library is not supported at that time, I do not know whether it is supported now.

Other:

  • The ASDK maintained by Facebook and Pinterest optimizes the rendering of views, as described in this blog post
  • Network request optimization:
    • Network request data cache: It can be cached for a long time, and the information can be directly obtained during the validity period of the request
    • Network request times optimization: limit requests before they start, cancel, and call back ——-AOP slicing oriented programming

2.6 Solve the problem

Minimize CPU and GPU resource consumption

2.6.1 optimization

  • Optimization of the CPU
    • Try to use lightweight objects, such as CALayer instead of UIView, for places that don’t handle events
    • Don’t make frequent calls to UIView properties such as frame, bounds, Transform, etc., and minimize unnecessary changes
    • Try to calculate the layout in advance, adjust the corresponding attributes at one time if necessary, do not modify the attributes more than once
    • Autolayout consumes more CPU resources than setting the frame directly
    • The image size should be exactly the same as the UIImageView size
    • Control the maximum number of concurrent threads
    • Try to put time-consuming operations into child threads: text processing (sizing, drawing); Image processing (decoding, rendering)
  • To optimize the GPU

    • Try to avoid the display of a large number of pictures in a short period of time, as far as possible to display a composite of multiple pictures
    • Minimize the number of views and levels
    • Reduce transparent views (alpha<1) and set Opaque to YES for opaque views
    • Try to avoid off-screen rendering
  • Avoid off-screen rendering

In OpenGL, the GPU has two rendering modes:

    • On-screen Rendering: renders On the current Screen, Rendering On the Screen buffer currently used for display;
    • Off-screen Rendering: Creates a new buffer outside the current Screen buffer for Rendering
    • Off-screen rendering is a performance drain
      • A new buffer needs to be created
      • In the whole process of off-screen rendering, the context needs to be changed several times, first from the current Screen (on-screen) to off-screen (off-screen); When the off-screen rendering is finished, the rendering results of the off-screen buffer are displayed on the screen, and the context needs to be switched from off-screen to the current screen
    • Off-screen rendering can result in:
      • ShouldRasterize = YES
      • Mask the layer mask
      • Layer. masksToBounds = YES and layer.cornerRadius >
      • Shadow, layer.shadowXXX, if layer.shadowPath is set it will not render off-screen

3 power consumption

3.1 Main sources of application power consumption are:

  • CPU Processing
  • Networks and Networking
  • Location, Location
  • Images, Graphics

3.2 Power consumption optimization:

  • Minimize CPU and GPU power consumption
  • Use less timer
  • Optimize I/O operations
    • Do not write small data frequently. It is better to write data in batches at a time
    • Consider dispatch_io for reading and writing large amounts of important data, which provides an API for asynchronously operating file I/O based on GCD. The system optimizes disk access with dispatch_io
    • For large amounts of data, it is recommended to use databases (such as SQLite and CoreData).
  • Network optimization
    • Reduce and compress network data
    • If the result of multiple requests is the same, try to use caching
    • Use breakpoint continuation, otherwise the same content may be transmitted multiple times when the network is unstable
    • Do not attempt to perform network requests when the network is unavailable
    • Allows users to cancel long-running or slow network operations and set appropriate timeouts
    • For example, when downloading video streams, instead of sending small packets, download the entire file directly or in large chunks. If you download ads, download several at a time and display them slowly. If you download emails, download several at a time, not one by one
  • Location optimization
    • If you just need to quickly determine the user’s location, it’s best to use the requestLocation method of CLLocationManager. After the locating is complete, the locating hardware is automatically powered off
    • If it’s not a navigation app, try not to update your location in real time and turn off location services when you’re done
    • Try to reduce the positioning accuracy, such as try not to use the highest accuracy kCLLocationAccuracyBest
    • Need background position, try to set up pausesLocationUpdatesAutomatically to YES, if the user is unlikely to move the system will automatically suspended position update
    • Try not to use startMonitoringSignificantLocationChanges, priority startMonitoringForRegion:
  • Hardware detection optimization
    • When the user moves, shakes or tilts the device, motion events are generated, which are detected by hardware such as accelerometers, gyroscopes and magnetometers. These hardware should be turned off when testing is not required

4 Thin the installation package

Installation packages (IPA) are mainly composed of executable files and resources, so the iOS installation package will be streamlined from these two aspects

4.1 Resources (Pictures, Audio and Video)

  • Take lossless compression
  • Remove unused resources

4.2 Thin executable files

  • Compiler optimization
    • Strip Linked Product, Make Strings read-only, Symbols Hidden by Default set to YES
    • Disable exception support, Enable C++ Exceptions, Enable Objective-C Exceptions set to NO, Other C Flags add -fno-exceptions
  • Detect unused Code using AppCode (www.jetbrains.com/objc/) : menu bar -> Code -> Inspect Code
  • Write the LLVM plug-in to detect duplicate code, uncalled code
  • Generate a LinkMap file, you can view the specific composition of executable files, which files are larger
    • You can use third-party tools to parse LinkMap files: github.com/huanxsd/Lin…

4.3 bitcode

Xcode7 has added a setting like this, which is turned on by default. After turning on the Bitcode Settings, the compiled package is not the final binary package but the bitcode intermediate code. Apple will optimize the bitcode according to the compiler and application device to give you the final, most optimized binary application package. This avoids the issue of Submitting an app package to the Appstore when Apple updates the compiler or hardware device. Also enjoy the benefits of compiler improvements.

The catch is that some third-party libraries don’t support Bitcode, so you have to turn it off if you want to use the corresponding third-party library. Due to a long time, I have forgotten which third party library is not supported at that time, I do not know whether it is supported now.

Other:

  • The ASDK maintained by Facebook and Pinterest optimizes the rendering of views
  • Network request optimization:
    • Network request data cache: It can be cached for a long time, and the information can be directly obtained during the validity period of the request
    • Network request times optimization: limit requests before they start, cancel, and call back ——-AOP slicing oriented programming

Green hills do not change, green water flow, thank you for your support, I hope this article can help you!!