Open and close markers
Requirement
A session report lists one user's events in order, bracketed by an
== SESSION OPEN == line before the first event and an
== SESSION CLOSE == line after the last. The four events
are in the code; both versions must print the lines shown under
Expected output.
Expected output
== SESSION OPEN == 09:12 login kim 09:14 open /reports 09:26 edit budget-aug 09:41 logout kim == SESSION CLOSE ==
Side by side
RxDart
FxDart
Why they differ
Almost nowhere: this is vocabulary parity. RxDart's
startWith injects a value before the source's first
emission and endWith injects one after the source
completes; FxDart's prepend and append are
the same two words on a pull chain, yielding the marker before the
first pull reaches the source and after the source runs dry. One
operator each, symmetric names, first-class on both sides.
The only model difference worth noticing is when the closing
marker can exist. On the push side endWith has to wait
for the done event — the marker's position is a fact about the
stream's lifecycle. On the pull side append is just the
next thing the iterator yields once the source is exhausted; there is
no lifecycle to observe, only demand. For a finite in-memory feed the
distinction is invisible, so this one is a tie — pick the model the
rest of your pipeline already lives in.
Benchmark
N = 100
Time Tie
Peak memory Tie
N = 1,000,000
Time FxDart wins
Peak memory RxDart wins
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.