Imaging process:

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

Imaging principle:

  • A vSYNC signal that tells the screen that a frame of data is about to be displayed;

  • Signal horizontal synchronization and display row by row of data until the entire screen is filled.

Causes of caton

  • As shown in the figure: The transmission frequency of vSYNC signal is fixed. When the signal is sent, it means that the data will be displayed.

  • If one step of the CPU or GPU takes a long time (

    Render for frame 3

    ), the vertical signal has been sent, but the GPU has not finished rendering, then the rendering is displayed

    Frame 2,

    Data, continuous display of the same frame, caused the picture to stall.

  • 3 frames

    It will be displayed when the fourth sync signal comes through.

So the main idea to solve Caton is:

  • Minimize CPU and GPU resource consumption. (keep the brush rate at 60FPS.)

CPU optimization:

  • Try to use lightweight objects, such as CALayer instead of UIView for places that do not handle events.

  • Do not frequently call UIView properties such as frame, bounds, and Transform properties to minimize unnecessary changes;

  • Try to calculate the layout in advance, adjust the corresponding attributes at one time when necessary, do not modify the attributes for many times;

  • Autolayout consumes more CPU than frame;

  • The image should be exactly the same size as the UIImageView;

  • Control the maximum number of concurrent threads.

  • Try to put time-consuming operations into child threads:

    1. Picture processing (decoding, drawing);
    2. Text processing (size calculation, drawing) :

    / / text calculation [@ “text” boundingRectWithSize: CGSizeMake (100, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:nil context:nil];

    [@”text” drawWithRect:CGRectMake(0, 0, 100) 100) options:NSStringDrawingUsesLineFragmentOrigin attributes:nil context:nil];

GPU optimization:

  • Try to avoid the display of a large number of pictures in a short period of time, as much as possible will be a composite picture display;

  • The maximum texture size that GPU can process is 4096×4096. Once this size is exceeded, CPU resources will be occupied for processing, so texture should not exceed this size.

  • Minimize the number and level of views;

  • Reduce transparent views (alpha<1) and set opaque to YES for opaque views;

  • Try to avoid off-screen rendering.

Caton detection

Ideas:

  • The common “lag” is mainly due to the execution of time-consuming operations 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. If the thread of the RunLoop takes too long to execute the method before it goes to sleep, or if it takes too long to receive messages after it wakes up and cannot proceed to the next step, the thread is considered blocked. If the thread is the main thread, it appears to be stuck.

    Once it is found that the state of kCFRunLoopBeforeSources before entering sleep or the state of kCFRunLoopAfterWaiting after awakening does not change within the set time threshold, it can be identified as stuck.

    The code to enable child thread monitoring is as follows:

    Dispatch_async (dispatch_get_global_queue(0, 0)) ^{// the child thread opens a continuous loop to monitor while (YES) {//semaphoreWait signal wait time long semaphoreWait = dispatch_semaphore_wait(dispatchSemaphore, dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC)); if (semaphoreWait ! = 0) { if (! runLoopObserver) { timeoutCount = 0; dispatchSemaphore = 0; runLoopActivity = 0; return; } / / BeforeSources and AfterWaiting to detect whether the two caton the if (runLoopActivity = = kCFRunLoopBeforeSources | | runLoopActivity = = KCFRunLoopAfterWaiting) {//end activity}// end semaphore wait timeoutCount = 0; }// end while }); Copy the codeCopy the code
  • Third party: LXDAppMonitor