Windowed alerts from a sensor stream
Requirement
A boiler temperature sensor delivers readings as a real Dart
Stream — one every 10 ms, twelve in total (fixed data,
in the code below). Group the stream into windows of four
readings, report each window's average and peak, and raise an
ALERT line for any window whose average is at or above
75.00.
FxDart's answer is its stream bridge: fxStream lifts the
Stream into the pull-based pipeline, and from there
windowing is just chunk(4) — the same operator the sync
examples use — followed by a map that summarizes each
window with averageBy and maxBy.
Expected output
boiler sensor, windows of 4 readings: 0s-3s avg 69.50 peak 70.5 4s-7s avg 75.75 peak 77.0 8s-11s avg 69.88 peak 72.0 ALERT 4s-7s: average 75.75 is above the 75.00 limit
Side by side
Native Dart
FxDart
Why they differ
Dart's Stream API has no windowing operator. The idiomatic
options are an await for loop with a mutable buffer —
accumulate four, flush, reset, as shown — or packaging that same
bookkeeping into a custom StreamTransformer, which is more
code, not less. Either way the buffer, the flush condition, and the
reset are yours to maintain, and the partial-window edge case is yours
to reason about. In FxDart, chunk(4) is one word on a
stream exactly as it is on a list — crossing from Stream
to pipeline costs one fxStream call, and the whole
operator vocabulary comes with it.
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 Native wins
N = 100,000
Time Native wins
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.