G
YouTube TikTok Games
Skip to main content

Debug performance for web apps

Learn how to profile Flutter web and WebAssembly apps, measure Core Web Vitals, and inspect Wasm footprint in Chrome DevTools.

The Flutter framework emits timeline events as it builds frames, draws scenes, and tracks runtime activity such as garbage collections. These events appear directly in the Chrome DevTools Performance panel for profiling and debugging.

To emit custom timeline events from Dart code, use the dart:developer Timeline and TimelineTask APIs, or record browser-level marks with the window.performance property (refer to Measure startup and frame milestones).

Screenshot of the Chrome DevTools performance panel

Build and run in profile mode

#

Always evaluate runtime performance in profile mode or release mode rather than debug mode. Choose the command that matches the metric under test:

What to measureCommandNotes
CPU, frame rendering, and memory flutter run -d chrome --profile (add --wasm for WebAssembly) Compiles with production optimizations ( -O2 for Wasm) while preserving symbol and WasmGC type names in traces and heap snapshots.
Deployable profile bundle flutter build web --profile (add --wasm for WebAssembly) Generates a static profile bundle in build/web for testing on staging hosts or target devices.
Download size and cold-start load flutter build web or flutter build web --wasm Builds a minified, symbol-stripped release bundle with production file sizes.

Configure optional timeline flags

#

To configure which widget and rendering timeline events are tracked, set any of the following top-level properties to true in main() before profiling:

To capture a frame trace:

  1. Optional: Set the tracing flags that you want to track to true in main().
  2. Launch the app in profile mode (flutter run -d chrome --profile, adding --wasm for WebAssembly builds).
  3. Open the Chrome DevTools Performance panel and record a runtime trace while reproducing the interaction.

Profile Core Web Vitals (LCP, INP, and CLS)

#

Record a trace in the Chrome DevTools Performance panel to evaluate Core Web Vitals and inspect Flutter-specific rendering behavior:

  • Largest Contentful Paint (LCP): In full-page Flutter web apps, Chrome often attributes LCP to the host HTML loading element (or initial canvas surface) rather than internal Flutter widgets.
    • Record a User Timing mark on the first Flutter frame to measure actual app readiness (refer to Measure startup and frame milestones).
    • Verify that flutter_bootstrap.js, Flutter's rendering engine, and main.dart.wasm (or main.dart.js) download in parallel without waterfalls (refer to Reduce cold-start latency).
  • Interaction to Next Paint (INP): Inspect the Main thread (plus WebAssembly worker threads when cross-origin isolation is active) around slow interactions for long tasks, synchronous layout or shader compilation spikes, or V8 garbage-collection pauses.
  • Cumulative Layout Shift (CLS): Verify that removing the HTML loading indicator or mounting embedded Flutter views with addView() doesn't shift surrounding DOM content (refer to Prevent Cumulative Layout Shift (CLS)).

Inspect Wasm module size and memory footprint

#

For general dart2wasm size and WasmGC heap profiling steps in Chrome DevTools, refer to Profile Wasm performance and footprint. In a Flutter Wasm app, also check the following Flutter-specific artifacts:

  • Bundle and asset payloads: Build a stripped release bundle (flutter build web --wasm) and inspect main.dart.wasm, Flutter's rendering engine .wasm binary, and assets/** in the Chrome DevTools Network panel. To reduce initial download size, refer to Measuring app size and Reduce cold-start latency (--enable-wasm-deferred-loading).
  • Engine and WasmGC memory: Run with --profile (or flutter build web --wasm --no-strip-wasm) when recording heap snapshots to inspect both Dart WasmGC objects on the V8 heap and WebAssembly.Memory linear memory allocated by Flutter's rendering engine.