“This is the 20th day of my participation in the First Challenge 2022. For details: First Challenge 2022.”
In our previous article “How does iOS Native Render differ from Flutter (part 1)”, we looked at how rendering works and how native rendering works. In this article, we will talk about how Flutter is rendered and how the front-end is rendered on iOS.
Flutter rendering
The Flutter interface is made up of widgets. All widgets make up the Widget Tree. When the page is updated, the Widget Tree is updated, then the Element Tree is updated, and finally the RenderObject Tree is updated.
The subsequent rendering process of Flutter includes Build, Wiget Tree, Element Tree, RenderObject Tree, Layout, Paint, Composited Layer, etc. Combine layers, generate textures, and submit rendering content to GPU for rasterization and composition using OpenGL interface. This is the C++ Layer of Flutter, using Skia library. After submitting to the GPU process, the process of compositing and displaying the screen is basically similar to iOS native, so the performance is similar. Flutter differs slightly from iOS native in its buffering strategy:
Flutter uses VSync + Triple Buffering. On iOS, Flutter uses VSync + Double Buffering.
Rendering pipeline
The Flutter rendering pipeline involves multiple steps:
- Take user input, such as touch screen events, which might generate some animation, and start building components and rendering them;
- Rendering can be broken down into 3 substeps;
Layout
(layout), which determines the size and position of each component on the screen;Paint
(Draw), which provides a set of methods to render components as they appear to the user;Composite
(Layer Composition) It stacks layers or textures generated by the drawing step and organizes them in order so that they can be efficiently rendered on the screen. Layer composition is a critical and final optimization step before components are rendered on the screen.
- Finally, rasterization, which maps an abstract representation to physical pixels on the screen.
The front-end rendering
Most of the front-end uses WebView under the WebKit framework. WebView requires additional parsing of HTML + CSS + JavaScript code, and when the content is loaded for the first time, WebView will be slower than native rendering.
In addition to the time it takes to load and parse the first time, and the performance problems caused by the slow interpretation of the JavaScript language itself, the WebView’s rendering process is separate, and each frame update calls the GPU process through IPC. Frequent IPC process communication also has a performance cost.
The WebView’s individual renderer cannot access the GPU context yet, so there is no way for the two processes to share texture resources. Texture resources cannot be rasterized using THE GPU Context directly, so they can only be transmitted to the GPU process through IPC, which results in GPU unable to give full play to its performance advantages. Because WebView rasterization cannot be synchronized to GPU in time, the white screen is easy to appear when sliding.
Write in the last
In comparison, it is not difficult to find that Flutter may perform as well as native Flutter in some aspects, and even surpass native Flutter in some aspects. In comparison, due to the multiple layers of WebView rendering, more restrictions, and more computation, Flutter is still weaker than native Flutter and Flutter in terms of performance and speed.