Skip to content

Commit 122ac9c

Browse files
committed
feat(site): a cost-per-request lens, additive and self-revealing
Two columns beside the existing ones - CPU per request, and requests per CPU-second. Nothing already shown changes: the board's strength is presenting one honest dataset several ways, so this is another lens rather than a replacement. WHY THE COLUMN IS NEEDED AT ALL. The throughput column stops describing the GATEWAY the moment one saturates its pinned cores; past that it describes the box, and two gateways at the wall read the same however different they are. Cost per request has no such ceiling: at saturation both deliver the same rps by definition, and the one doing less work per request still reads lower. GATED ON THE BOARD ANSWERING THEM, following the per-cell-memory precedent. This is not hiding an absence, and the distinction matters: every OTHER column shows "not measured" per row, because a row missing one metric still has the rest. A cost column on a board measured before the capture existed would be n/a on EVERY row - a column asking a question nothing on the page can answer, which is noise rather than disclosure. It lights up by itself on the first board carrying the field. Sorted ASCENDING, because less CPU per request is better - the opposite of the throughput column beside it, and the sort direction is the only thing on the page that says so. TWO THINGS THE GUARDS CAUGHT, both mine: - The C5 accessor lint fired on `c.cpu_us_per_request.value`. A raw read bypasses the below_resolution rule, where a null value with that reason IS a measurement. Routed through mval(). The lint did exactly its job on the first line written the wrong way. - Proving the gate red, I reverted app.js with `git checkout --` and lost the whole feature rather than the one mutated line. Both COST tests failed with the feature gone, which is at least the right kind of evidence, and the work is reapplied intact. Tests: 204 passing (up from 202), both new ones proven red first - one pins that the columns are absent on a cost-less board and present on a cost-carrying one, the other that an unmeasured cost renders "not measured" and never a 0 that would make the least-measured gateway look like the cheapest on the board.
1 parent 0a49e70 commit 122ac9c

2 files changed

Lines changed: 90 additions & 3 deletions

File tree

‎site/app.js‎

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,6 +1049,28 @@ function hasPerCellMemory(data = (typeof state !== "undefined" ? state.data : nu
10491049
PER_CELL_MEM_CACHE.set(data, yes);
10501050
return yes;
10511051
}
1052+
/* hasCost(data): does ANY gateway on this board carry a measured cost-per-request?
1053+
The cost columns follow the per-cell-memory precedent above and appear only when the board can
1054+
answer them. This is not hiding an absence: every OTHER column shows "not measured" per row,
1055+
because a row that lacks one metric still has the rest. A cost column on a board measured before
1056+
the capture existed would be n/a on EVERY row - a column that asks a question nothing on the page
1057+
can answer, which is noise rather than disclosure. It lights up by itself on the first board that
1058+
carries the field. */
1059+
const COST_CACHE = new WeakMap();
1060+
function hasCost(data = (typeof state !== "undefined" ? state.data : null)) {
1061+
if (!data || typeof data !== "object") return false;
1062+
if (COST_CACHE.has(data)) return COST_CACHE.get(data);
1063+
const yes = (data.gateways || []).some((g) => {
1064+
const cells = [g.best_cell, g.translation_cell].filter(Boolean);
1065+
// THROUGH mval(), not a raw .value read. C5 exists because a raw read bypasses the
1066+
// below_resolution rule (an envelope whose value is null but whose reason means "measured, too
1067+
// small to weigh" IS a measurement), and the lint caught this line the first time it was
1068+
// written the other way.
1069+
return cells.some((c) => mval(c.cpu_us_per_request) != null);
1070+
});
1071+
COST_CACHE.set(data, yes);
1072+
return yes;
1073+
}
10521074
// The data bundle a (possibly synthetic) state refers to; falls back to the live state's.
10531075
function stateData(st) {
10541076
return (st && st.data) || (typeof state !== "undefined" ? state.data : null);
@@ -1694,6 +1716,22 @@ const COLUMN_SETS = {
16941716
use - which is exactly what the two columns this replaces did ("Sustained RPS (20 ms upstream)", with
16951717
a tooltip asserting a p99 < 1 s bar the engine never enforced, over a metric read at 20 ms).
16961718
Switching the bound re-reads this column and re-sorts the table in front of the reader. */
1719+
/* WHAT A REQUEST COST, beside what it delivered. `costOnly` keeps these off a board that cannot
1720+
answer them (see hasCost); they light up on the first run carrying the capture.
1721+
WHY THIS COLUMN EXISTS AT ALL: the throughput column stops describing the GATEWAY the moment
1722+
one saturates its pinned cores - past that it describes the box, and two gateways at the wall
1723+
read the same however different they are. Cost per request has no such ceiling: at saturation
1724+
both deliver the same rps by definition, and the one doing less work per request still reads
1725+
lower. Ascending, because less CPU per request is better. */
1726+
{ id: "cpu", label: "CPU per request (\u00b5s)", desc: false, costOnly: true,
1727+
title: () => `Microseconds of gateway CPU - user plus system, summed across its whole process tree - spent per completed request, ` +
1728+
`measured at a fixed concurrency held identical for every gateway (published beside it as the cost window). ` +
1729+
`Unlike peak throughput this does not stop separating gateways once they saturate their cores. ` +
1730+
`A window with any failure publishes no cost: CPU divided by only the successes would describe the failures, not the work.`,
1731+
get: (g) => chooserPerfCell(g, "cpu_us_per_request", fmt2) },
1732+
{ id: "rpscpu", label: "Requests per CPU-second", desc: true, costOnly: true,
1733+
title: "The same fact the way a box is sized: completed requests per second of gateway CPU burned. Higher is cheaper to run.",
1734+
get: (g) => chooserPerfCell(g, "rps_per_cpu_second", fmtInt) },
16971735
{ id: "rps", label: () => boundColLabel(selectedBound()), desc: true,
16981736
title: () => `The most requests/sec the chosen cell carried ${boundClause(selectedBound())} and it failed no request it accepted, with the concurrency it was observed at. ` +
16991737
`One of ${BOUND_CHOICES.length} readings of the SAME concurrency sweep published on every cell - switch the bound above to re-rank the board. ` +
@@ -1880,8 +1918,10 @@ function txt(x) { return typeof x === "function" ? String(x() ?? "") : String(x
18801918
perCellOnly exists only where the data can fill it: the published board still carries bundles measured
18811919
before per-cell memory, and a growth column that reads n/a on all thirteen rows would be noise. */
18821920
function columnsFor(view, data = (typeof state !== "undefined" ? state.data : null)) {
1883-
const cols = COLUMN_SETS[view] || COLUMN_SETS.performance;
1884-
return hasPerCellMemory(data) ? cols : cols.filter((c) => !c.perCellOnly);
1921+
let cols = COLUMN_SETS[view] || COLUMN_SETS.performance;
1922+
if (!hasPerCellMemory(data)) cols = cols.filter((c) => !c.perCellOnly);
1923+
if (!hasCost(data)) cols = cols.filter((c) => !c.costOnly);
1924+
return cols;
18851925
}
18861926
/* rowComparator(col, desc): the roster's row order for one column and one direction.
18871927
THE NAME TIEBREAK IS NOT PART OF WHAT THE READER ASKED TO REVERSE. Toggling a column to descending
@@ -4847,7 +4887,7 @@ if (NODE) {
48474887
perCellMemory, memoryCells, hasPerCellMemory, widestDialect, chosenMemory, memoryFor,
48484888
idleAcrossCells, neverPlateaued, worstGrowth, memCellTip, neverPlateauedPill,
48494889
idleStatic, memShape, memGrowing, memShaped,
4850-
hasMatrixGrid, matrixFailureReason, matrixRoster,
4890+
hasMatrixGrid, matrixFailureReason, matrixRoster, hasCost,
48514891
laneRecord, lanePathNote, perfSweepSeries, concAt,
48524892
// THE FRONTIER: the constants (mirrored from seal.mjs and checked against it), the readers every
48534893
// surface goes through, and the two renderers that make the curve's SHAPE legible. Exported because the

‎site/test.mjs‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2246,6 +2246,53 @@ test("stripRigPaths scrubs absolute bench-box paths from diagnostic notes", () =
22462246
assert.ok(!na.note.includes("/home/"));
22472247
});
22482248

2249+
test("COST: the cost columns appear only on a board that can answer them, and read through the envelope", () => {
2250+
// ADDITIVE, NOT A REPLACEMENT. The existing columns are untouched; these follow the per-cell-memory
2251+
// precedent and appear only when the board carries the field.
2252+
//
2253+
// WHY GATE AT ALL, when every other absence renders per row: a row missing ONE metric still has the
2254+
// rest, so "not measured" there is disclosure. A cost column on a board measured before the capture
2255+
// existed is n/a on EVERY row - a column asking a question nothing on the page can answer, which is
2256+
// noise. It lights up by itself on the first board carrying the field.
2257+
const noCost = { gateways: [{ key: "a", best_cell: bcCell({}) }] };
2258+
assert.equal(app.hasCost(noCost), false);
2259+
const ids = app.columnsFor("performance", noCost).map((c) => c.id);
2260+
assert.ok(!ids.includes("cpu"), `no cost column on a board without cost: ${ids.join(",")}`);
2261+
assert.ok(ids.includes("rps"), "the throughput column is untouched");
2262+
2263+
// A board that DOES carry cost shows them, and reads the value through the sealed envelope.
2264+
const withCost = {
2265+
gateways: [{
2266+
key: "a",
2267+
best_cell: { ...bcCell({}), cpu_us_per_request: seal(37.5), rps_per_cpu_second: seal(26666) },
2268+
}],
2269+
};
2270+
assert.equal(app.hasCost(withCost), true);
2271+
const cols = app.columnsFor("performance", withCost);
2272+
const cpu = cols.find((c) => c.id === "cpu");
2273+
assert.ok(cpu, "the cost column appears once the board can answer it");
2274+
assert.equal(cpu.desc, false, "less CPU per request is better, so it sorts ascending");
2275+
const st = { data: withCost, mode: "peak", bound: 10 };
2276+
assert.equal(cpu.get(withCost.gateways[0], st).v, 37.5);
2277+
assert.equal(cols.find((c) => c.id === "rpscpu").get(withCost.gateways[0], st).v, 26666);
2278+
});
2279+
2280+
test("COST: an absent cost renders 'not measured', never a 0 that would look infinitely efficient", () => {
2281+
// A gateway measured before the capture existed carries a null envelope. Rendering that as 0 would
2282+
// make the LEAST-measured gateway look like the cheapest one on the board.
2283+
const board = {
2284+
gateways: [
2285+
{ key: "measured", best_cell: { ...bcCell({}), cpu_us_per_request: seal(40) } },
2286+
{ key: "not-yet", best_cell: { ...bcCell({}), cpu_us_per_request: seal(null, { reason: "not_measured" }) } },
2287+
],
2288+
};
2289+
const cpu = app.columnsFor("performance", board).find((c) => c.id === "cpu");
2290+
const st = { data: board, mode: "peak", bound: 10 };
2291+
const absent = cpu.get(board.gateways[1], st);
2292+
assert.equal(absent.v, null, "an unmeasured cost has no value");
2293+
assert.ok(!/^0/.test(absent.text), `must not render as a zero: ${absent.text}`);
2294+
});
2295+
22492296
test("FINDING 39: a sub-1/s rate survives every axis tick and every hover sentence", () => {
22502297
// THE RATE HAS NOW LEAKED AT SIXTEEN BOUNDARIES ACROSS FIVE AUDIT ROUNDS, always the same shape:
22512298
// one renderer is taught the fractional rate and a sibling reading the SAME number is missed. These

0 commit comments

Comments
 (0)