A stream feeds a typed pipeline
Requirement
A live log feed emits seven lines on a fixed schedule and closes. Keep only the warnings, uppercase them for the incident channel, and print them with a final count. The feed is simulated in the code (identically on both sides); both versions must print the lines shown under Expected output.
Expected output
WARN: DISK 81% FULL WARN: LATENCY 900MS WARN: RETRY QUEUE AT 12 warnings: 3
Side by side
RxDart
FxDart
Why they differ
They barely do — and that is the point of this pair. The source is a
push-native thing, a Stream that emits when it pleases,
and RxDart stays in that model: mapNotNull filters and
formats in one operator, toList collects at close. Clean,
idiomatic, done.
The FxDart side does not fight the stream and does not re-model the
source — it bridges it. fxStream wraps any
Stream as a pull-based async iterable, and from that
point on the code is the same typed chain you would write over a
list: filter, map, toList. The
bridge buffers pushed events until the pipeline demands them, so
nothing is lost and order is preserved. This is a cooperation example,
not a contest: let the stream be a stream at the edge where events are
born, and cross into a pull pipeline the moment you want typed,
demand-driven processing — the two models compose in one line. Tie,
and deliberately so.
Benchmark
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
Peak memory Tie
N = 10,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.