By Xie Wei (Wei Sheng)
As mentioned in the previous article “Optimization Practice of Flutter Smoothness”, although the effect of the first phase is obvious, there is still a big gap from the ultimate user experience. Last year, Tao Terminal architecture and the business team jointly launched the project of “Ultimate Experience Optimization of Basic Link”, aiming to achieve ultimate experience in terms of duration and fluency. This article will explain in detail the second phase of Tao Flutter fluency optimization practice.
The optimization effect
First, let’s briefly review the results of the last phase of optimization. In the first phase, the main optimization measures were focused on “business best practices” and the optimization results were still good without changing the Engine or building the wheel. This proves that Flutter can maintain good performance in complex business scenarios as long as it has sufficient practical experience.
However, with the optimization of Tao Tao entering the deep water zone, due to the pursuit of the ultimate user experience and the race of Native performance data, we began to quickly absorb the experience of outstanding predecessors from the group and the industry and make breakthroughs on our own. Finally, after completing a number of key technological breakthroughs such as “Hummer engine upgrade”, “self-developed ExternalImage Image library” and “self-developed FlowView high-performance streaming container”, the second phase achievements are as follows:
Note: Fluency fluctuates with business iteration and test caliber. The above data are from: Taute 4.14.0 double-ended slow sliding test caliber (sliding rate refer to the screen recording below)
From the perspective of body sensing recording screen, there are two major improvements:
- The fluency is improved again, and there is basically no lag in double-end slow sliding
- Eliminate the iOS lag problem
Android screen recording comparison (left before optimization, right after optimization)
For the video, please click: Tao Flutter Fluency Optimization Practice phase II
IOS screen recording comparison (left before optimization, right after optimization)
For the video, please click: Tao Flutter Fluency Optimization Practice phase II
Key techniques in the optimization process
Engine upgrade Hummer
I believe many students have heard of Hummer engine (UC Flutter custom engine). Thanks to UC’s rich experience in rendering performance optimization and the AliFlutter community ecology, Taobao decided to add Hummer after thorough investigation. However, in the process of adding Hummer, In turn, Taute and Hummer encountered a lot of complex scenes that needed to be solved in terms of fluency, load time, memory, and so on.
First of all, the fluency optimization brought by the upgrade of Hummer engine is mainly in the following four aspects. The specific principles refer to the introduction of Hummer engine. This paper focuses on the actual problems and solutions solved by Tao and the comparison effect of the upgrade.
Here is the final result of the engine upgrade:
Taute Android4.4.0 baseline
Tao iOS4.6.0 baseline
Dual-end frame rate and lag rate have been significantly improved, especially iOS end to solve the problem that Feeds stream is easy to lag under iPhone6. And upgrade engine to tao te’s biggest impact is the upgrade of external photo library.
Image gallery comparison of Flutter
In the case of fluency, the choice of photo library is crucial. The cost of migrating the original CDNImage (the external image library solution of the old Engine coupled Engine) in Hummer Engine was too high, forcing Tolt to look for a new “non-invasive image library solution”.
At the beginning, we tried to use NetworkImage to get first-hand experience data. Fluency ascension is very obvious, but the shortage of the NetworkImage meet only short-term rapid gray, the FImage (external texture image gallery) appeared in front of us, is a very efficient solution, but found that after the measured low-end machine fluency is slightly down before, we began to explore more suitable for tao’s photo gallery.
Finally, ExternalImage was developed by ourselves, and the effect surpassed CDNImage in the comparison of smoothness and loading time.
Here is a comparison of group Flutter’s main gallery solutions:
The following is the frame consumption performance chart of ExternalImage and external Texture scheme under Hummer. We find that the Raster thread frame consumption of external Texture scheme is significantly higher than that of the original Image component scheme. Preliminary analysis is that the excessive Texture makes the low-end machine consume too much time and load on Raster. Since frame_time is approximately equal to Max (UI, raster), when raster takes more than 16ms, the actual motional FPS decreases. And that brings us to the ExternalImage gallery in the next section.
Tao ExternalImage photo library
The above is an overall architecture diagram of ExternalImage, which loads pixel data from Native based on FFI. Starting from the official Image component, the Provider initiates Channel call, gets the picture and returns the result, triggers decode, setState and other processes. Green indicates the request link and yellow indicates the return link.
The core technologies are as follows:
Tao Flow-View lightweight Flow container
List scrolling has always been a key scene of Flutter smoothness optimization. Before obtaining Hummer engine optimization, the smoothness optimization once encountered a bottleneck. In Flutter’s official streaming container design philosophy, Element is considered a very lightweight component that does not support reuse when scrolling through lists. As elements are added or subtracted from the list, the Widget is considered very lightweight and does not have a local refresh. This is severely challenged in tao’s actual complex Feeds business scenario. We developed a lightweight Flow container solution flow-View based on the business characteristics. Supports the following two features:
- Partial refresh, which will enable the page to load more existing ItemWidgets without having to repeatedly build them;
- Element/RenderObject reuse makes scrolling into new elements more efficient.
FlowView is partially refreshed
We first look at the diagram on the right of the above figure. In the local refresh scenario, adding a new element before optimization on the left will trigger setState to trigger the entire list Rebuild. After optimization on the right, insert only the two new elements, and Rebuild is not required for the existing elements.
Source left for the details, by SliverMultiBoxAdaptorElement. The update method, by scrolling to the bottom, and newDelegate. ChildCount > oldDelegate judgment to load more scenario to perform partial refresh (i.e., insert a new element).
FlowView Element and RenderObject reuse
In the scroll scene, when new elements 12 and 13 are about to enter the screen, a new Element and RenderObject will be created on the left before optimization. The new elements 12 and 13 on the right will reuse the elements 0 and 1 removed from the top, Element and RenderObject. Do recycling, more efficient.
Source left for the details, when obtaining new insert item by SliverMultiBoxAdaptorElement. CreateChild method, Before optimization _childElements[index]=null, Element and RenderObjec creation will be triggered. After optimization, updateChild will be triggered if there are any reusable elements according to the type of the new Element. If the cache is not empty, The didUpdateWidget logic is executed.
RemoveChild no longer deactive Element (that is, does not trigger updateChild) when an Element is removed. At the same time, by modifying the framework removes RenderObject from ContainerRenderObjectMixin two-way chain table (RenderObject. _removeFromChildList). Add Element to cacheMap.
Android Sliding feel
In Taote, we not only pay attention to the improvement of fluency data, but also pay more attention to the actual body sensation of users. After a certain version upgrade, Android feels less smooth than before, and the damping sensation increases significantly at the beginning of sliding. The following video comparison.
1. Optimization before 4.2.0
For the video, please click: Tao Flutter Fluency Optimization Practice phase II
2. Optimized 4.3.0
For the video, please click: Tao Flutter Fluency Optimization Practice phase II
The reason for this is that the BouncingScrollSimulation based pull-down refresh component has changed the Simulation of the Android platform. Simulation sliding algorithm of Android and iOS platform is analyzed.
We decided to differentiate Simulation algorithms on Android based on whether they scroll to the end. Until we scroll to the bottom, we still use ClampingScrollSimulation to keep the feel similar to Android native. After we scroll to the end, we switch to ScrollSpringSimulation to support pull-down refresh. Based on the dynamic switching algorithm encapsulates a generic BouncingableClampingScrollSimulation for business use.
Summary and Prospect
To sum up, in the first and second phase of optimization, the optimization of Flutter smoothness achieved good results in offline tests, and some pages exceeded Native. The lower end is also stable at higher frame rates. But the real scene of online users is far more complex than offline, so Tao tao will increase investment in the following three aspects this year.
- From offline to online, participate in the construction and construction of AliFlutter-APM full-link performance analysis platform.
- In terms of models, tao, focus on the low end of the machine before from experience to the experience of all models optimization, the program such as sliding interpolator caton tuning, high iphones refresh and upgrade FlutterImageView/SurfaceTexture power.
- Finally, a large part of the previous optimization work was dedicated to manual optimization. In the future, more process automation will be implemented, such as alarm tools for low-performance widgets and integrated performance bayonet tools, to ensure high quality and low cost of business to maintain the optimization results.
【 References 】
[1] Xiao Yu: Research on Flutter Performance Profiling and Theory
[2] : Xianyu Cloud: He doubled the smoothness of the long list of Xianyu apps
[3] : Google Android RecyclerView. ViewHolder: RecyclerView. Adapter# onCreateViewHolder
[4] : Jank and Stutter stall rate explanation
[5] : Tao Flutter Fluency Optimization practice