このページはまだ翻訳されていないため、英語で表示されます。 翻訳に参加する

Fetch 4 at a time, results in order

FxDart wins async

Requirement

Fetch eight user profiles whose response times differ, keeping at most 4 requests in flight at once — and print the results in source order (user 1 first), plus the maximum observed in-flight count as proof of the bound. The delays are in the code; both versions must print the lines shown under Expected output.

Expected output
user#1
user#2
user#3
user#4
user#5
user#6
user#7
user#8
max in flight: 4

Side by side

RxDart

FxDart

Why they differ

Both sides bound the concurrency in one operator, and the shared counter shows both genuinely hit 4 in flight. The split is over order. flatMap(maxConcurrent: 4) is a merge: it emits each inner result the moment it completes, so with these delays user 7 (10 ms) would print before user 1 (80 ms). To meet the requirement the RxDart side tags every result with its id, collects everything, and sorts afterwards — the ordering the source had is destroyed by the merge and must be rebuilt by hand at the end.

mapConcurrent(4, fetch) never loses the order in the first place. In a pull pipeline, concurrency is a property of demand, not of delivery: the operator issues four overlapping pulls but hands results downstream in the order they were asked for, holding a fast late arrival until its slower predecessors are out. Bounded-and-ordered is the shape most batch work actually wants — results lined up with inputs, rate limits respected — and it is the default here rather than a reconstruction. When completion order is what you actually want, that exists too — concurrentPool, the next example — but it is the variant you opt into, not the behavior you undo.

Benchmark

Apple M1 Max, 32 GB RAM · Dart 3.12.2 (AOT-compiled) · 2026-08-18

Async case: the headline scale is N = 10,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

RxDart 767 µs
FxDart 377 µs

Peak memory Tie

RxDart 16.6 MB
FxDart 17.2 MB

N = 10,000

Time FxDart wins

RxDart 60.9 ms
FxDart 32.3 ms

Peak memory FxDart wins

RxDart 51.7 MB
FxDart 22.2 MB

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.