p50/p95 latency per endpoint
Requirement
From raw request logs (data in the code), drop failed requests and
compute p50 and p95 latency per endpoint: sort each
endpoint's latencies and take the value at index
round((n-1) * q / 100). Print a table sorted by worst p95
first, then call out the worst endpoint. Both versions must print the
table under Expected output.
Expected output
Latency percentiles (successful requests only) /orders p50 133 ms p95 620 ms (5 reqs) /search p50 210 ms p95 480 ms (4 reqs) /users p50 88 ms p95 340 ms (5 reqs) Worst p95: /orders at 620 ms
Side by side
Native Dart
FxDart
Why they differ
A percentile is "sort, then index" — in FxDart that is literally
sortBy + nth, applied inside a
groupBy → map pipeline that turns each
endpoint group into a stats row; ranking the table and finding the worst
endpoint reuse the same rows with sortBy and
maxBy. The native version does the same math but through a
mutable row list filled in a for loop, an in-place
..sort(), raw index access, and a reduce
comparator for the maximum. Both are correct; the fxdart side keeps
"group → summarize → rank" as three visible strokes instead of one loop
doing all three at once.
Benchmark
N = 100
Time Tie
Peak memory Tie
N = 10,000
Time Tie
Peak memory FxDart wins
N = 1,000,000
Time Tie
Peak memory Native 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.