When developing a terminal, the first thing to consider is the rendering of views and animations, switching, etc. The most direct experience of users when using an app is whether the interface looks good, whether the animations are dazzling, and whether the sliding flow is smooth. The UI is the facade of the app, and its experience accompanies the entire process of the user using the app. If the UI fails, the user will not have the desire to open the app a second time. iOS provides developers with a rich framework (UIKit, Core Animation, Core Graphic, OpenGL, etc.) to meet various development needs from top to bottom. I have to say that Apple is awesome. You don't need to understand the principles behind many interfaces to get started and meet most of your needs. However, if you encounter performance problems, it's easy to be at a loss. Ease of use and optimization are contradictory. Just like ARC, it's very enjoyable to use when you don't encounter memory problems. Once you encounter them, you will be required to understand the memory mechanism of iOS better than when using MRC. The same is true for UI. Moreover, as an employee of Tencent, of course we can't just know how to use it. We must know the whys and the whys. Okay, without further ado, let's get to the point: see how iOS renders views and animations, and how to optimize when we encounter rendering performance problems. (Note: The following content is some of the author's experience and summary, welcome to discuss!) Let's first take a look at the official description of Core Animation: It can be seen that the core of iOS rendering view is Core Animation. From the bottom to the top, it is GPU->(OpenGL, Core Graphics)->Core Animation->UIKit. On iOS, animation and view rendering are actually done in another process (hereinafter we call this process render server). Before iOS 5, this process was called SpringBoard, and after iOS 6 it was called BackBoard. The following picture shows the progress of the entire system when using the project to record a video (a large number of view rendering): You can clearly see the status of the BackBoard process. The various stages of view or animation rendering on iOS: There are 4 stages inside the APP:
2 stages outside the APP: When this data reaches the render server, it will be deserialized into a render tree. Then the render server will do the following two things:
If you are doing an animation, the last two steps will be repeated until the animation is finished. We all know that the screen refresh rate of iOS devices is 60HZ. If the above steps cannot be completed within one refresh cycle (1/60s), it will cause frame drops. Let's see which operations may consume too much CPU or GPU and cause frame drops.
If the view hierarchy is too complex, the CPU will spend more time recalculating the frame when some views are rendered or the frame is modified. This is especially true if autolayout is used. At the same time, too many geometric structures will greatly increase the number of OpenGL triangles that need to be rendered and the number of rasterization operations (converting OpenGL triangles into pixels).
Notes on rendering performance optimization: Hidden drawing: Both CATextLayer and UILabel draw text into the backing image. If the frame of a view containing text is changed, the text will be redrawn. Rasterize: When using the layer's shouldRasterize (remember to set the appropriate layer's rasterizationScale), the layer will be forced to draw to an offscreen image and cached. This method can be used to cache layers that are time-consuming to draw (such as those with more gorgeous effects) but are not often changed. If the layer changes frequently, it is not suitable. Off-screen drawing: Use rounded corners, layer masks, and stretchable images to achieve drop shadows. For example, to achieve rounded corners, assign a circular image to the content property of the layer, and set the contentsCenter and contentScale properties. Blending and Overdraw: If a layer is completely covered by another layer, the GPU will optimize and not render the covered layer, but calculating whether a layer is completely covered by another layer is very CPU-intensive. Blending the colors of several semi-transparent layers together is also very CPU-intensive. What we are going to do:
This will reduce blending and overdraw. If you use an image, try to avoid setting the image's alpha to transparent. If some effects require the fusion of several images, let the designer draw it with one picture, and don't let the program merge them dynamically when running. OK, now that we have introduced the points to note for rendering optimization, let’s look at some specific examples using the Core Animation and GPU Driver instruments. Core Animation: Color Blended Layers: Check the coverage of the semi-transparent layer. From green to red, the redder the color, the greater the coverage. The following two pictures show the measurement of the semi-transparent layer of the project details page. You can see that there are still many semi-transparent layers on the details page, but it does not mean that if there are many semi-transparent layers, the range is large and optimization is required. You need to refer to the measurement of GPU Driver to see, which will be introduced below. Color Hits Green and Misses Red: When using shouldRasterize, the layer drawing will be cached. If the rasterized layer needs to be redrawn, it will be marked in red. The following is the case where the cell of the project message list is set to shouldRasterize = YES. The backing image of each cell's layer will be cached. If the tableview is scrolled down, the cell will be reused, so the layer will be redrawn and marked in red. Color Offscreen-Rendered Yellow: If you want to do offscreen drawing, it will be marked in yellow. Below is the homepage of the project. Since the circular avatar is implemented by setting the property of roundedCorner, it will trigger offscreen drawing. The Core Animation Template only allows developers to intuitively see which areas may need optimization, but whether to optimize or not still depends on the performance of the GPU Driver. GPU Driver Renderer Utilization - If this value is greater than 50%, it means that the GPU performance is limited by fill-rate, there may be too much Offscreen rendering, overdraw, and blending. Tiler Utilization - If this value is greater than 50%, it means there may be too many layers. Let’s take the project details page above as an example and look at the GPU driver measurements: You can see that the Renderer Utilization is about 20%, and the Tiler Utilization is 15%, so there is no need for optimization. (Of course, we are not considering the CPU usage here, but only based on some measurements of the Core Animation Template above, we can say that there is no need for targeted optimization.) What I want to say here is that the above points only provide us with optimization directions and ideas when we encounter rendering performance problems. Optimization often means more complex and difficult to understand code. Don't over-optimize when you don't encounter rendering performance problems. |
<<: Apps with data - data expressions on mobile phones
>>: The Programming Story of Little Printf: Chapter 2
What is the price for joining the Hohhot Meat and...
Some time ago, I had in-depth communication and u...
Teacher Yuan Haotong - Introduction to mixing and...
Early this morning, Apple released the official v...
Pineapple Season Edition Ye Tan Wine Bureau Pinea...
Expert of this article: Pan Kunming, Master of Ph...
Recently, the whistleblower @Upleaks released spy...
The customer service group was shouting: This use...
[[387969]] Last night, CCTV's 315 Gala expose...
Do you have the problem of repeated lip peeling? ...
Produced by: Science Popularization China Author:...
Most people regard routine annual physical examin...
Someone asked, what is the job of operations? In ...
"Sun Jian's Premium Family Education Cour...
One of the four great traditional classics A new ...