A four-state empirical CDF that bins nothing — one step curve per group on a shared percent axis, percentiles read off the steps themselves, named crossings between curves, a keyboard-driven scan line and a vertex cap that states its own error.
Preview in your theme
Loading preview…
This component is part of Pro
The install command, prompt and concept map are included with a Pro license — one purchase unlocks every Pro component, forever.
status="ready" · 350 requests across three releases, every one of them on the curve, with no bin width anywhere in the picture. v4.3 is the fastest release at p50 (303 ms) and still the fastest at p90 (398 ms) — then its curve goes flat at 95% while the other two climb to 100%, because seven of its 140 requests took more than a second. The card names where the curves swap places (548 ms against v4.2, 412 ms against the canary); a table of medians and p90s cannot contain that fact. Drag anywhere on the plot, or tab in and use the arrow keys, to read all three shares at one value.
Response time by release
3 groups · 350 requests · p50 spans 303 ms to 424 ms · the curves cross
at 364 msv4.2 17.5% (21/120)v4.3 82.1% (115/140)v4.4-canary 57.8% (52/90)
v4.2 · 120 requests · p50 424 ms · p90 533 ms · max 631 ms
v4.3 · 140 requests · p50 303 ms · p90 398 ms · max 2,590 ms
v4.4-canary · 90 requests · p50 357 ms · p90 406 ms · max 483 ms
v4.2 and v4.3 swap places near 548 ms — one is ahead for the lower part of the sample and behind for the upper part, which is the comparison a pair of medians cannot report.v4.3 and v4.4-canary swap places near 412 ms — one is ahead for the lower part of the sample and behind for the upper part, which is the comparison a pair of medians cannot report.
Each curve is the share of that group at or below the response time under it, with no bins chosen and nothing smoothed. Percentiles are read off the step itself — the smallest reading with at least that share at or below it — so a marker is always a point of the curve. Tab to the plot and use the arrow keys, Home, End or Page keys to move the scan.
Response time by release— one row per group. Each figure is read off the empirical cumulative distribution: the share of a group at or below a value, ties included, with no binning anywhere. Percentiles are the smallest reading whose share reaches the level, so they are values that were actually measured rather than interpolated ones; a box plot's median may therefore sit slightly lower on an even-sized sample.
Group
Requests
Lowest
p50
p90
Highest
At 364 ms
v4.2
120
272 ms
424 ms (50% at or below)
533 ms (90% at or below)
631 ms
17.5%
v4.3
140
174 ms
303 ms (50.7% at or below)
398 ms (90% at or below)
2,590 ms
82.1%
v4.4-canary
90
265 ms
357 ms (50% at or below)
406 ms (90% at or below)
483 ms
57.8%
onScanChange → not moved yet
status="empty" · a valid contract with not one reading, worded so it cannot be mistaken for loading or for a failed fetch.
Response time by release
Share of requests at or below each response time, with no bins to choose
No requests to accumulate
An ECDF is built from the raw readings — one number per event. Bucket counts, a mean or a percentile table cannot be turned back into the curve they came from.
status="loading" · two skeleton staircases, aria-hidden, honouring prefers-reduced-motion, with no timer involved.
Response time by release
Share of requests at or below each response time, with no bins to choose
Loading requests
status="error" · the fetch failed. Try again only appears when onRetry is passed, and clicking it flips the card to ready.
Response time by release
Share of requests at or below each response time, with no bins to choose
Couldn't load these requests
The data source didn't respond.
Awkward samples · n=1 (canary) is a single riser from 0% to 100% at 296 ms, which is exactly what one observation knows and no more. retired shard was measured and returned nothing, so it keeps its legend row and says so instead of quietly disappearing. cached fixture is forty runs that all landed on 250 ms — one step, one full-height riser, and the tie is the finding rather than something to jitter apart. Three readings arrived without a usable number: they are dropped, counted out loud, and never folded into a denominator. The last label is far too long for the plot, so it elides on the curve with the full name on its tooltip and in the legend.
Awkward samples
4 groups · 65 runs · p50 spans 213 ms to 296 ms · the curves cross · 3 left out for want of a number
canary · 1 run · p50 296 ms · p90 296 ms · max 296 ms
retired shard · measured, no runs recorded
cached fixture · 40 runs · p50 250 ms · p90 250 ms · max 250 ms
provisioned-concurrency-warm-pool (eu-west-1) · 24 runs · p50 213 ms · p90 250 ms · max 270 ms · 3 unusable
cached fixture and provisioned-concurrency-warm-pool (eu-west-1) swap places near 250 ms — one is ahead for the lower part of the sample and behind for the upper part, which is the comparison a pair of medians cannot report.
3 runs arrived without a usable number and were left out of every figure here — dropped values are counted, never quietly absorbed into a denominator.
Each curve is the share of that group at or below the duration under it, with no bins chosen and nothing smoothed. Percentiles are read off the step itself — the smallest reading with at least that share at or below it — so a marker is always a point of the curve. Tab to the plot and use the arrow keys, Home, End or Page keys to move the scan.
Awkward samples— one row per group. Each figure is read off the empirical cumulative distribution: the share of a group at or below a value, ties included, with no binning anywhere. Percentiles are the smallest reading whose share reaches the level, so they are values that were actually measured rather than interpolated ones; a box plot's median may therefore sit slightly lower on an even-sized sample.
Group
Runs
Lowest
p50
p90
Highest
At 213 ms
canary
1
296 ms
296 ms (100% at or below)
296 ms (100% at or below)
296 ms
0%
retired shard
0
no runs recorded
cached fixture
40
250 ms
250 ms (100% at or below)
250 ms (100% at or below)
250 ms
0%
provisioned-concurrency-warm-pool (eu-west-1)
24 (3 unusable)
182 ms
213 ms (50% at or below)
250 ms (91.7% at or below)
270 ms
50%
Too many vertices, said out loud · 2,700 requests against the default maxVertices={600}. burst window has 851 distinct readings and draws 600 of them — every k-th distinct reading with both ends kept, so the fastest and the slowest survive — and the card states that the drawn curve sits at most 0.5% below the exact one, a gap measured from the vertices actually kept rather than asserted from the ratio. steady window is under the cap and draws all 238. p50 (700 ms) and p90 (1,078 ms) come from all 2,200 readings, never from a sample of them.
Time to first byte, two windows
2 groups · 2,700 requests · p50 spans 440 ms to 700 ms
at 709 msburst window 51.3% (1,129/2,200)steady window 99.2% (496/500)
burst window · 2,200 requests · p50 700 ms · p90 1,078 ms · max 2,559 ms
steady window · 500 requests · p50 440 ms · p90 545 ms · max 851 ms
Too many distinct requests to give each its own vertex, so burst window draws 600 of 851. Every k-th reading with both ends kept, which leaves the drawn curve at most 0.5% below the exact one — measured, not assumed. Percentiles, extremes and every scan reading use the whole sample.
Each curve is the share of that group at or below the time to first byte under it, with no bins chosen and nothing smoothed. Percentiles are read off the step itself — the smallest reading with at least that share at or below it — so a marker is always a point of the curve. Tab to the plot and use the arrow keys, Home, End or Page keys to move the scan.
Time to first byte, two windows— one row per group. Each figure is read off the empirical cumulative distribution: the share of a group at or below a value, ties included, with no binning anywhere. Percentiles are the smallest reading whose share reaches the level, so they are values that were actually measured rather than interpolated ones; a box plot's median may therefore sit slightly lower on an even-sized sample.
Group
Requests
Lowest
p50
p90
Highest
At 709 ms
burst window
2,200
248 ms
700 ms (50% at or below)
1,078 ms (90% at or below)
2,559 ms
51.3%
steady window
500
201 ms
440 ms (50.2% at or below)
545 ms (90% at or below)
851 ms
99.2%
maxVertices={900} on the same data · nothing is thinned now, all 851 vertices are drawn, and the notice disappears because there is nothing left to disclose. The picture barely changes, which is the point of printing the gap: half a percent is what the cheaper curve was costing, and now you can decide whether it was worth paying for.
Time to first byte, two windows
2 groups · 2,700 requests · p50 spans 440 ms to 700 ms
at 757 msburst window 59.3% (1,305/2,200)steady window 99.6% (498/500)
burst window · 2,200 requests · p50 700 ms · p90 1,078 ms · max 2,559 ms
steady window · 500 requests · p50 440 ms · p90 545 ms · max 851 ms
Each curve is the share of that group at or below the time to first byte under it, with no bins chosen and nothing smoothed. Percentiles are read off the step itself — the smallest reading with at least that share at or below it — so a marker is always a point of the curve. Tab to the plot and use the arrow keys, Home, End or Page keys to move the scan.
Time to first byte, two windows— one row per group. Each figure is read off the empirical cumulative distribution: the share of a group at or below a value, ties included, with no binning anywhere. Percentiles are the smallest reading whose share reaches the level, so they are values that were actually measured rather than interpolated ones; a box plot's median may therefore sit slightly lower on an even-sized sample.
Group
Requests
Lowest
p50
p90
Highest
At 757 ms
burst window
2,200
248 ms
700 ms (50% at or below)
1,078 ms (90% at or below)
2,559 ms
59.3%
steady window
500
201 ms
440 ms (50.2% at or below)
545 ms (90% at or below)
851 ms
99.6%
guides={[0.25, 0.5, 0.75, 0.95]} height={300} · four percent levels is the cap, because a fifth dashed rule stops being a reference and starts being a grid; levels outside (0, 1) are dropped, since 0% and 100% are the axis ends. Every marker sits on the riser of its own curve — the smallest reading whose share reaches the level, not an interpolated quantile floating beside the line it claims to read — and each curve steps its name off the dashed rules so a label never reads as a caption for a guide.
Response time by release
3 groups · 350 requests · p50 spans 303 ms to 424 ms · the curves cross
at 364 msv4.2 17.5% (21/120)v4.3 82.1% (115/140)v4.4-canary 57.8% (52/90)
v4.2 · 120 requests · p25 380 ms · p50 424 ms · p75 488 ms · p95 544 ms · max 631 ms
v4.3 · 140 requests · p25 266 ms · p50 303 ms · p75 349 ms · p95 445 ms · max 2,590 ms
v4.4-canary · 90 requests · p25 327 ms · p50 357 ms · p75 387 ms · p95 432 ms · max 483 ms
v4.2 and v4.3 swap places near 548 ms — one is ahead for the lower part of the sample and behind for the upper part, which is the comparison a pair of medians cannot report.v4.3 and v4.4-canary swap places near 412 ms — one is ahead for the lower part of the sample and behind for the upper part, which is the comparison a pair of medians cannot report.
Each curve is the share of that group at or below the response time under it, with no bins chosen and nothing smoothed. Percentiles are read off the step itself — the smallest reading with at least that share at or below it — so a marker is always a point of the curve. Tab to the plot and use the arrow keys, Home, End or Page keys to move the scan.
Response time by release— one row per group. Each figure is read off the empirical cumulative distribution: the share of a group at or below a value, ties included, with no binning anywhere. Percentiles are the smallest reading whose share reaches the level, so they are values that were actually measured rather than interpolated ones; a box plot's median may therefore sit slightly lower on an even-sized sample.
Group
Requests
Lowest
p25
p50
p75
p95
Highest
At 364 ms
v4.2
120
272 ms
380 ms (25% at or below)
424 ms (50% at or below)
488 ms (75% at or below)
544 ms (95% at or below)
631 ms
17.5%
v4.3
140
174 ms
266 ms (25% at or below)
303 ms (50.7% at or below)
349 ms (75.7% at or below)
445 ms (95% at or below)
2,590 ms
82.1%
v4.4-canary
90
265 ms
327 ms (25.6% at or below)
357 ms (50% at or below)
387 ms (75.6% at or below)
432 ms (95.6% at or below)
483 ms
57.8%
Negative values + showObservations="always" · revenue change per account against a holdout, so the axis grows a dashed rule at zero and the share of losers is something you read off the curve rather than infer: 22 of 64 Variant A accounts and 25 of 48 holdout accounts came out below it. Variant A's curve is to the right of the holdout's at every value — no crossing anywhere, which says the treatment moved the whole distribution and not just its middle. Dotting every step corner is honest at n=64; past a few hundred it turns the staircase into a smear, which is why "auto" stops at 40.
Revenue change per account vs. control
2 groups · 112 accounts · p50 spans -788 USD to 1,859 USD
at 1,282 USDVariant A 42.2% (27/64)Holdout 60.4% (29/48)
Variant A · 64 accounts · p50 1,859 USD · p90 12,463 USD · max 21,040 USD
Each curve is the share of that group at or below the revenue change under it, with no bins chosen and nothing smoothed. Percentiles are read off the step itself — the smallest reading with at least that share at or below it — so a marker is always a point of the curve. Tab to the plot and use the arrow keys, Home, End or Page keys to move the scan.
Revenue change per account vs. control— one row per group. Each figure is read off the empirical cumulative distribution: the share of a group at or below a value, ties included, with no binning anywhere. Percentiles are the smallest reading whose share reaches the level, so they are values that were actually measured rather than interpolated ones; a box plot's median may therefore sit slightly lower on an even-sized sample.