Load three remote configs in order
Requirement
Load three remote config sections — features,
limits, theme — from a (simulated) API,
one at a time, in order, then print each loaded value.
The fake fetch takes a fixed 15 ms; both versions must print the lines
shown under Expected output.
Expected output
features -> {darkMode: true, beta: false}
limits -> {maxUpload: 25, rateLimit: 120}
theme -> {accent: teal, density: compact}
Side by side
Native Dart
FxDart
Why they differ
For three sequential awaits, the native for loop is
perfectly fine — nobody needs a library to write it, and if the story
ended here this would be a tie. The FxDart win is what the code becomes
next: toAsync().map(fetchConfig) is a lazy async pipeline
that is serial by default, and the day you have thirty configs
instead of three, appending .concurrent(8) turns the same
chain into a bounded worker pool — order preserved, nothing else
touched. The native loop has no such dial; it gets rewritten. See
Fetch profiles, two at a time for
that ending.
Benchmark
Async case: the headline scale is N = 100,000, not 1,000,000. Every element costs an event-loop turn on both sides, so a million real awaits would measure Dart's event loop for minutes — not the pipeline. Delays are zero-length and the example's concurrency limit is kept; what the bars compare is the pipeline machinery.
N = 100
Time Tie
Peak memory Tie
N = 10,000
Time Tie
Peak memory Tie
N = 100,000
Time Tie
Peak memory Tie
Bars are medians of repeated timed iterations in fresh processes per side (small N is batched for timer resolution). Sides within 5% of each other — or within 0.6 ms, a difference no person can perceive — count as a tie; close relative races are re-measured up to 5 runs. In an app, anything under a few milliseconds is invisible to the user regardless of which bar is shorter. Memory is peak process RSS. The Dart VM and the dataset are identical on both sides, so the difference between the two bars is what the pipeline itself holds onto.