The CPU and GPU

  • In the process of screen imaging, CPU and GPU play a crucial role
    • CPU (Central Processing Unit)

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

      • Texture rendering

  • In iOS, it is double buffering mechanism, with frame caching before and frame caching after

Principles of screen imaging

The cause of caton

  • The main idea of Catton’s solution
    • Minimize CPU and GPU resource consumption
  • At a brush rate of 60FPS, a VSync signal is generated every 16ms

Caton optimization – 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 (size calculation, drawing)
    • Image processing (decoding, rendering)
  • 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
  • The maximum texture size that GPU can process is 4096×4096. Once the texture size exceeds this size, IT will occupy CPU resources for processing, so the texture size should not exceed this size
  • 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

Off-screen rendering

  • In OpenGL, the GPU has 2 rendering methods
    • On-screen Rendering: Renders 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
  • What actions trigger an off-screen rendering?
    • ShouldRasterize = YES

    • Mask the layer mask

    • Rounded corners with layer.masksToBounds = YES and layer.cornerRadius > 0

      • Consider using CoreGraphics to draw rounded corners, or ask an artist to provide rounded images
    • Shadow layer. ShadowXXX

      • If layer.shadowPath is set, off-screen rendering will not occur

Caton detection

  • The “lag” is usually referred to as a time-consuming operation performed on the main thread
  • You can add an Observer to the main RunLoop to monitor the lag by listening for the time it takes for the RunLoop state to change

Major source of electricity consumption

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

Optimize the power consumption

  • 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

The start of the APP

  • APP startup can be divided into two types

    • Cold Launch: Start an APP from scratch
    • Warm Launch: The APP is already in memory and alive in the background. Click the icon again to Launch the APP
  • The optimization of APP startup time is mainly for cold startup

  • Print APP startup time analysis by adding environment variables (Edit Scheme -> Run -> Arguments)

    • DYLD_PRINT_STATISTICS is set to 1
    • If you need more detailed information, set DYLD_PRINT_STATISTICS_DETAILS to 1

  • As shown in figure display
    • Pre-main time: the time before the main function is called
    • Dylib loading time: dynamic library loading
    • Rebase/binding time:
    • ObjC Setup Time: structure preparation time
    • Initializer Time: indicates the initialization time
    • Grammar intializers: libraries that are busy loading
      • libsystem.dylib
      • libMainThreadChecker.dylib
  • Print in more detail

  • Anything less than 400 milliseconds is acceptable

  • The cold start of APP can be summarized into three stages
    • dyld
    • runtime
    • main

APP startup – dyld

  • Dyld (Dynamic Link Editor), Apple’s dynamic linker, which can be used to load Mach-O files (executables, dynamic libraries, etc.)
  • When you launch your APP, dyld does a couple of things
    • Load the APP’s executable file, Mach-o, and recursively load all dependent dynamic libraries
    • When dyLD finishes loading the executable and dynamic libraries, it notifies Runtime for further processing

APP startup – Runtime

  • When you start your APP, the Runtime does the following

    • Map_images is called for parsing and processing of executable file contents
    • Call call_load_methods in load_images and call the +load method for all classes and categories
    • Initialize various objC structures (register objC classes, initialize class objects, and so on)
    • Calls the C++ static initializer and the __attribute__(((constructor)) modified function
  • Up to this point, all symbols (Class, Protocol, Selector, IMP,…) in executables and dynamic libraries All have been successfully loaded into memory in the format managed by the Runtime

APP startup – main

  • To summarize
    • The startup of the APP is dominated by dyLD, which loads the executable into memory, along with all the dependent dynamic libraries
    • The Runtime is responsible for loading the structure defined by objC
    • When all initialization is complete, Dyld calls the main function
    • Next came the UIApplicationMain function, AppDelegate application: didFinishLaunchingWithOptions: method

APP startup optimization

  • According to different stages
    • dyld

      • Reduce dynamic libraries, merge some dynamic libraries (periodically purge unnecessary dynamic libraries)
      • Reduce the number of Objc classes and classes, reduce the number of selectors (periodically clean up unnecessary classes and classes)
      • Reduce the number of C++ virtual functions
      • Swift uses structs as much as possible
    • runtime

      • Replace all __attribute__(((constructor)), C++ static constructors, and ObjC + loads with the +initialize method and dispatch_once method
    • main

      • Delay as much as possible without affecting the user experience, and don’t put everything into the finishLaunching method
      • According to the need to load

Mounting package slimming

  • Installation package (IPA) mainly consists of executable files and resources

  • Resources (pictures, audio, video, etc.)

    • Take lossless compression
    • Remove unused resources: github.com/tinymind/LS…
  • 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
    • Use AppCode (www.jetbrains.com/objc/) to detect unused… -> Code -> Inspect Code

    • Write the LLVM plug-in to detect duplicate code, uncalled code

LinkMap

  • Generate a LinkMap file to view the specific composition of the executable file

  • You can use third-party tools to parse LinkMap files: github.com/huanxsd/Lin…