WASM For Improved Flutter App Performance

Jackie Moraa
7 min readDec 17, 2024

--

WebAssembly which is often abbreviated as WASM is a low-level binary-instruction (assembly like) code format and a corresponding text format for executable programs. It is designed to provide a portable compilation target for programming languages like C/C++ and Rust enabling them to run on the web.

WASM features

  1. High performance: WASM is a compact binary format that enables faster execution than e.g., JavaScript because it smaller and runs closer to machine code (near native performance). This smaller binary format results in faster downloads and reduced latency for web applications. WASM is therefore particularly suited for high computational tasks that require substantial resources. E.g., scientific simulations, mathematical calculations, gaming, video processing, animations etc.
  2. Agnostic: WASM is both platform and language agnostic. It can run on any platform that supports it. Various high-level languages can also be compiled to WASM. This flexibility allows developers to still work with their preferred language for their specific use case and leverage on the existing libraries and ecosystems from their chosen language.
  3. JS interoperability: WebAssembly integrates very well with JavaScript, so it can be used to boost web apps while still relying on JavaScript for the other web app functionality.
  4. Security: WASM runs in a secure sandboxed environment in the browser, which limits potential harm from malicious code. It also incorporates memory safety features to prevent common vulnerabilities like buffer overflows, and code validation ensures only trusted code runs. This makes it a suitable choice for handling sensitive data and cryptographic operations.

How it works

When code is written in a high-level language like C or Rust, a WebAssembly-compatible compiler will convert it into WASM bytecode. This bytecode is a compact and efficient representation of the original code.

When a web page containing WASM bytecode code is loaded, the browser’s WASM engine fetches this compiled module and translates the bytecode into machine code, which can be executed directly by the underlying system.

WASM code is typically compiled just-in-time (JIT) i.e., as it is needed for execution. This JIT compilation ensures that the code is optimised for the specific device and platform on which it is running, resulting in the near-native performance. JIT makes the application ideal for resource-demanding tasks such as gaming & scientific computations — which we mentioned earlier.

Flutter Web Application

The architecture below is that of a standard Flutter web application. It shows the different layers involved in rendering a Flutter app on the web and how they interact. c/o Kevin Moore from the WASM I/O 2023.

Application Code: This is where actual Flutter app code resides. It is written in Dart and it defines the UI components, business logic, interactions etc. of the web app.

Flutter Framework: This layer provides the core functionalities of Flutter like the widget system and rendering pipeline.

Flutter Engine: It is in this layer that the compilation and execution of the Dart code into JavaScript is handled. It also handles the communication between the Dart code and the browser’s environment.

Skia (CanvasKit): Skia is a C++ library that provides the rendering capabilities for the Flutter app. It’s compiled into WebAssembly (WASM) format to be executed efficiently in the browser. Flutter apps on the web ship with a WASM version of the Skia renderer called CanvasKit.

Compilation and Execution
When you run flutter build web, the Dart code, along with the Flutter framework and engine are compiled into JavaScript. The compiled JavaScript code is executed in the browser by the JavaScript engine. Skia is compiled into WebAssembly, is also loaded into the browser and used for rendering the UI.

This architecture still works great but with the advancements of WASMGC, it is now possible to ship the whole Flutter app as one WASM package as detailed in the next section.

WASM & Flutter

WASM support is available on the Flutter stable channel. So to use WASM with Flutter Web App, upgrade your Flutter SDK to version >= 3.22.

Also, to run a Flutter app that has been compiled to WASM, you’ll need a browser that supports WASMGC. E.g., Chrome version >= 119, Firefox version >= 120 (but with a bug), and Safari (still under active development — see bug here).

WASMGC is an extension to the WebAssembly specification that makes it easier to port garbage-collected programming languages to WASM.

Garbage collection (GC) is a memory recovery feature built into programming languages such as Dart, Kotlin, C# and Java. A GC-enabled programming language provides a way to automatically free up memory space that has been allocated to objects when they no longer needed them.

WASMGC adds instructions which allow developers to use the existing garbage collector of a programming language instead of recompiling it for WASM.

To test if your Chrome browser supports WASMGC, simply run the line below. The output should be function

console.log(typeof WebAssembly.instantiate);

PS. Before using WASM with Flutter, it should be noted that as of mid this year, many packages still don’t support WASM. Web-based dependencies/packages/libraries (e.g., imports of dart:html, dart:js, etc) can’t be compiled on WASM.

Also, now that the SDK version is upgraded to >= 3.22 it is important to initialise your Flutter Web App as required by this higher version. Use this script by placing an async-script tag for it in your index.html file in the web subdirectory of your Flutter app.

Then to build the Flutter web app with WASM add the flag --wasm to the end of the build command as: flutter build web — wasm

So, how does the architecture compilation differ with the standard web app?

c/o Kevin Moore from the WASM I/O 2023.

With WASM, the most notable change is that the entire Flutter app, framework and engine are packaged and shipped as a single WASM bundle as well as the Skia library as indicated by the .wasm extension. The dart code is compiled using the dart2wasm tool.

However, even with the --wasm flag, Flutter will still compile the application to JavaScript. If WASMGC support is not detected at runtime, the JavaScript output is used so the application will continue to work in all major browsers.

Standard JS vs WASM analysis

I built a simple web app to analyse the performance differences when compiled to JS vs WASM — Same code base. Serve the built outputs to your local machine e.g., python -m http.server 8080. (Use different ports for the different deployments). Ps. Using a Flutter Version Management tool will help with this. Check out my previous article for steps on that. Then get on the performance tab on the inspect element side panel to view the metrics detailed below.

Loading: This is the time spent retrieving resources like HTML, JavaScript, and CSS files.

Scripting: This phase includes parsing, compiling, and executing the JavaScript code.

Rendering: This time represents layout and style calculations done by the browser to render the UI elements.

Painting: This is the time spent drawing the UI elements onto the screen after rendering is complete.

System: This covers time used by the system for processes outside of the core web rendering pipeline e.g., garbage collection, disk I/O etc.

Idle: This is time spent by the browser as it waits for other tasks to be completed.

Standard JS — Flutter v3.19
With WASM — Flutter v3.24

With WASM, the loading, rendering and painting times are shorter than with the standard JS version. The differences are not that significant as this is just a simple app, but when dealing with heavy simulations, computations or animations, the milliseconds start to add up.

The WASM app exhibits a much higher scripting time but this is likely due to the additional overhead of loading and processing the WASM module.

Also, check out the video below on the comparison.

WASM is a fairly new concept for me, so if some details are missing or incorrect, kindly let me know. Have you worked with WASM & Flutter before? If yes, do you recommend? I enjoyed reading and learning about it and I hope this article sparked the same feeling for you.

“The difference between ordinary and extraordinary is that little extra.”
— Jimmy Johnson

And for the last time in 2024, thank you so much for reading ❤

--

--

Jackie Moraa
Jackie Moraa

Written by Jackie Moraa

Google Developer Expert - Flutter & Dart. Still on a learning journey. ❤

Responses (1)