Flutter is fast, beautiful, productive and open for every platform we support. In Flutter 1.20, which is released on 5 August 2020 to our stable channel, Flutter has improvements for every one of these four pillars. In this article, we will discuss Jank Improvements in Flutter 1.20 Release.
To enable you to build Flutter apps that are ever more beautiful, 1.20 release has several UI enhancements, including the long-awaited features like listed below:
- Support for autofill
- Jank Improvements
- A new way to layer your widgets to support pan and zoom
- New mouse cursor support
- Updates to old favorite Material widgets such as the time and date pickers.
- A whole new responsive license page for the About box in your desktop and mobile form-factor Flutter apps.
- Null safety has been added to dart.dev
In this article, we will discuss the Jank Improvements on mobile in detail in Flutter 1.20.
What is shader compilation jank?
If an app has janky animations during the first run, and later becomes smooth for the same animation, then it’s very likely due to shader compilation jank.
More technically, a shader is a piece of code that runs on a GPU (graphics processing unit). When a shader is first used, it needs to be compiled on the device. The compilation could cost up to a few hundred milliseconds whereas a smooth frame needs to be drawn within 16 milliseconds for a 60 fps (frame-per-second) display. Therefore, a compilation could cause tens of frames to be missed, and drop the fps from 60 to 6. This is compilation jank. After the compilation is complete, the animation should be smooth.
If the animations on your mobile app appear to be janky, but only on the first run, you can warm up the shader captured in the Skia Shader Language (SkSL) for a significant improvement.
Jank Improvements in Flutter
What do we mean by “first-run”?
On Android, “first-run” means that the user might see jank the first time opening the app after a fresh installation. Subsequent runs should be fine.
On iOS, “first run” means that the user might see jank when an animation first occurs every time the user opens the app from scratch.
How to use SkSL warmup?
- As of release 1.20, Flutter provides command-line tools for app developers to collect shaders that might be needed for end-users in the SkSL (Skia Shader Language) format. The SkSL shaders can then be packaged into the app, and get warmed up (pre-compiled) when an end-user first opens the app, thereby reducing the compilation jank in later animations. Use the following instructions to collect and package the SkSL shaders:
flutter run --profile --cache-sksl
- Play with the app to trigger as many animations as needed; particularly those with compilation jank.
- Press M at the command line of flutter run to write the captured SkSL shaders into a file named something like flutter_01.sksl.json.
- Build the app with SkSL warm-up using the following, as appropriate:
flutter build apk --bundle-sksl-path flutter_01.sksl.json
flutter build ios --bundle-sksl-path flutter_01.sksl.json
Test the newly built app. Alternatively, you can write some integration tests to automate the first three steps using a single command. For example:
flutter drive --profile --cache-sksl --write-sksl-on-exit flutter_01.sksl.json -t test_driver/app.dart
With such integration tests, you can easily and reliably get the new SkSLs when the app code changes, or when Flutter upgrades. Such tests can also be used to verify the performance change before and after the SkSL warm-up. Even better, you can put those tests into a CI (continuous integration) system so the SkSLs are generated and tested automatically over the lifetime of an app.
Take the original version of Flutter Gallery as an example. The CI system is set up to generate SkSL for every Flutter commit, and verifies the performance, in the transitions_perf_test.dart test.
The worst frame rasterization time is a nice metric from such integration tests to indicate the severity of shader compilation jank. For instance, the steps above reduce Flutter gallery’s shader compilation jank and speed up its worst frame rasterization time on a Moto G4 from ~90 ms to ~40 ms. On iPhone 4s it’s reduced from ~300 ms to ~80 ms.
Limitations and considerations
Why not just compile or warm-up all possible shaders?
If there are only a limited number of possible shaders, then Flutter could do a warm-up and compile all of them before-hand to avoid such jank. However, for the best overall performance, the Skia GPU backend used by Flutter can dynamically generate shaders based on a lot of parameters at runtime (for example, draws, device models, and driver versions). Due to all possible combinations of those parameters, the number of possible shaders is exponential. In short, Flutter uses programs (app, Flutter, and Skia code) to generate some other programs (shaders). The number of possible shader programs that Flutter can generate is simply too large.
Can SkSLs captured from one device help shader compilation jank on another device?
Theoretically, there’s no guarantee that the SkSLs from one device would help on another device (but they also won’t cause any troubles if SkSLs aren’t compatible across devices). Practically, as shown in the table on this SkSL-based warmup issue, SkSLs works surprisingly well even if
1) SkSLs are captured from iOS and then applied to Android devices, 2) SkSLs are captured from emulators and then applied to real mobile devices.
As the Flutter team has only a limited number of devices in the lab, we currently don’t have enough data to provide a big picture of cross-device helpfulness.
Kindly go through our article DateRangePicker & Time Picker With Flutter 1.20 Release.
Thanks for being with us!!!
Do let us know your valuable feedback/suggestion to serve you better.