Part 2 · 1 chapters · ~8 min

Dart and Isolates

Dart's JIT for development (hot reload) and AOT for release, sound null safety, the event loop with microtask and event queues, async and await, isolates as separate heaps with message passing, Isolate.run and compute measured, transferable data, long-lived worker isolates, and memory and garbage collection in Dart.

4

Measured: keep heavy work off the UI isolate

code
final sw = Stopwatch()..start();
final list = jsonDecode(payload) as List;                         // on the UI isolate: blocks frames
print('${sw.elapsedMicroseconds / 1000} ms');                     // AOT: 6.0-7.0 ms (JIT first run: 16.8 ms)

final n = await Isolate.run(() => (jsonDecode(payload) as List).length);   // UI isolate free meanwhile
// AOT: ~6.3 ms total · empty Isolate.run round trip: 0.04-0.3 ms

// in Flutter: parse straight into models inside the isolate and return them
final txs = await Isolate.run(() => (jsonDecode(body) as List).map((j) => Tx.fromJson(j)).toList());

Event loop: each isolate runs one thread with a microtask queue (drained first, after every event) and an event queue (I/O, timers, gestures), like JavaScript's. A long synchronous loop blocks both. JIT and AOT: development builds use the JIT for hot reload; release builds are AOT-compiled to native code, which is why profiling must happen in profile or release mode (the first JIT decode above took 16.8 ms).

DART: PARSING ON THE MAIN ISOLATE VS Isolate.run
Dart 3.11.1 AOT on an Apple M3 Pro laptop, 791 KB / 5,000 transactions
frame budget at 60 Hz16.7 msjsonDecode on main isolate6.0-7.0 msIsolate.run(jsonDecode) total6.3 ms (main free)Isolate.run empty round trip0.04-0.3 ms
swipe the figure sideways, or tap expand for full screen
1/4
the budget
At 60 Hz the UI isolate has 16.7 ms per frame for build, layout, paint and any of your code that runs then.
16.7 ms per frame8.3 ms at 120 Hz