Fetch 10 profiles, 3 at a time
Requirement
From a directory of twelve accounts, take the active ones, order them by id, and fetch each profile from a (simulated) API — never more than three requests in flight, results in the original order. The fake fetch counts overlapping requests and both versions print the maximum observed, proving the limit held. The data is in the code below.
This is the flagship shape of the whole async section: a sync pipeline
(filter → sortBy) that crosses into async with
toAsync and keeps going — map the fetch,
concurrent(3) to bound it, one more map to
format, join to finish. One chain from list to report.
Expected output
fetched 10 profiles, 3 at a time: user#1 Ada <ada@example.com> user#2 Bram <bram@example.com> user#4 Dana <dana@example.com> user#5 Eli <eli@example.com> user#6 Fay <fay@example.com> user#7 Gus <gus@example.com> user#9 Ines <ines@example.com> user#10 Jun <jun@example.com> user#11 Kira <kira@example.com> user#12 Liam <liam@example.com> max requests in flight: 3
Side by side
Native Dart
FxDart
Why they differ
Plain Dart handles the sync half fine (where +
sortedBy), but at the async boundary the vocabulary runs
out: bounding concurrency while preserving order means a hand-rolled
worker pool — shared cursor, pre-sized result slots, a
Future.wait over the workers. That pool is real production
boilerplate, and it splits the task into two dialects: a fluent chain
for prep, then imperative plumbing for the fetch. In the FxDart version
the policy stays declarative end to end — concurrent(3) is
the entire worker pool, and changing the limit (or dropping it) touches
one number instead of the function's shape.
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 FxDart wins
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.