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

Keep values AND failures in the audit

FxDart wins

Requirement

A deploy audit parses eight key=value config lines, three of which have unparseable values. The report needs both halves: print each successfully parsed key = value, then a count of the failures. The lines are in the code; both versions must print the output shown under Expected output.

Expected output
timeout = 30
port = 8080
workers = 4
ttl = 300
batch = 25
failures: 3

Side by side

RxDart

FxDart

Why they differ

The stream model carries errors on a separate, out-of-band channel — and that channel is terminal: one FormatException ends the whole subscription, taking the five good lines with it. To keep values and failures, the RxDart side has to give every line its own inner stream (Rx.fromCallable) and convert the error into data before it can escape — onErrorReturn(null) here, with null standing in for "this one failed". That is the lightest spelling the model allows for a throwing function (the heavier materialize route reifies full notification objects), and it exists only to undo a decision the model made for you: errors were never values to begin with. (Both panels share the same throwing parse on purpose — with a null-returning parser both models could keep outcomes as plain data; the throw is the premise, and what each side must do about it is the comparison.)

The pull side never puts failures on a channel in the first place. The same throw lands one local try/catch away from being an ordinary value again — a nullable record — so the whole requirement is map then partition: one pass, two lists, both halves equally first-class. This is the shape of FxDart's broader typed-errors stance (its Either pipelines are this same idea with richer error types). When failures are part of the report rather than an exceptional end, keeping them as data wins — the verdict goes to FxDart.

Benchmark

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

N = 100

Time Tie

RxDart 465 µs
FxDart 100 µs

Peak memory Tie

RxDart 16.6 MB
FxDart 16.4 MB

N = 1,000,000

Time FxDart wins

RxDart 3894.3 ms
FxDart 995.7 ms

Peak memory Tie

RxDart 184.3 MB
FxDart 185.3 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.