Live Reports¶
Two lanes publish measurements continuously, to two pages on the
gh-pages branch. Neither is committed to main — the data only
exists where it was produced.
-
Every wheel built across all three SNOC nodes at once, with CPU, memory, compiler-cache and registry traffic sampled throughout. Opens on the newest run, with a selector for every earlier one.
Driven by hand with
make perf-coldormake perf-warm, published withmake perf-publish PUSH=1from a build node. How it works. -
Nightly Builds — data/nightly/
One warm bake per architecture on a rented AWS CodeBuild machine, 02:17 UTC, published to ECR. Phase wall clock and cache-error counts, every run kept. A table, not a chart — see below.
Fully automated, and it files a comment on one
nightly-labelled issue as well. How it works, what it costs.
The two are not comparable
A fleet run is a parallel build across three nodes sharing a compiler cache. A nightly is sequential bakes on one rented machine, and its phase wall clock is the whole bake rather than a per-target cost. Quoting one as the other is the mistake both pages open by warning about.
A third set of numbers — isolated per-target costs under four cache conditions — lives on Performance, and is not comparable with either.
Browsing Older Runs¶
Both pages keep everything ever published, and both open on the newest run — but they are not the same page, and only one of them charts.
data/perf/ is the interactive chart. perfsite.py writes a
runs.json and a runs/<stamp>.json beside it, which the page fetches
relative to its own URL to populate a selector; every run also keeps a
data/perf/<stamp>/ permalink. Pick any past run from the dropdown and
you get its full chart — overlaid CPU and memory, a legend that filters
by builder and target, per-band hover.
data/nightly/ is a table, plus one bar chart. nightlysite.py
writes a row per run and architecture — cold, warm, cost, sccache hit
rate, layer-cache hits — with a data/nightly/<stamp>/ permalink and
its own runs.json. Above the table, build-time.svg plots warm wall
clock per night, one bar group per architecture. No legend filtering,
no per-target spans, no sampled series.
The chart appears only once there are two runs to compare: one bar is not a series, and drawing it would imply a trend that cannot exist.
The sampled chart does not cover the AWS runs, and cannot
Not an oversight, and the distinction is narrower than "no chart".
A rented CodeBuild machine has none of what the fleet chart is drawn
from: there is no node_exporter on three nodes to sample into
samples.jsonl, no per-target trace-<target>.json, and no Zot or
nginx log to slice. None of that becomes available by wanting it.
What a nightly can see is its own wall clock, the instance it was
billed on, and what its phase logs already printed — which is what
build-time.svg and the cost and cache columns are drawn from, and
nothing more. A nightly times bake invocations and claims nothing it
cannot see.
nightlysite.py is deliberately a separate index for the same
reason the admonition above gives. Merging the two selectors would
put a parallel three-node run and a sequential one-machine run in
the same dropdown, which is the not-comparable mistake made
structural.
Watching A Run Live¶
For fleet runs, the published page is not a different tool from the
local one — perf-publish puts the chart perf-serve renders onto
gh-pages and adds the cross-run selector. So the same interface works
on a run that is still going:
make perf-serve # newest run, http://<host>:8090
make perf-serve-status # whether one is up, and where
make perf-serve-stop # stop it, free PERF_PORT
It regenerates every 30 s and re-resolves which run is newest each
cycle, so it picks up a run that starts after the server did. The page
polls data.json rather than reloading, because the legend is the
filter — a reload would discard whichever builders and targets you had
narrowed to. A published run is frozen and stops polling.
perf-serve binds every interface
0.0.0.0 by default, because the usual viewer is a laptop on the
LAN rather than on the tailnet. What that exposes is build
telemetry — hostnames, CPU and memory figures, build step names —
with no credentials and no registry access. Narrow it with
PERF_BIND=<ip>, and make perf-serve-stop when you are done.
What Each Publishes¶
| Fleet runs | Nightly | |
|---|---|---|
| Where | data/perf/<stamp>/ |
data/nightly/<stamp>/<arch>/ |
| Who runs it | an operator, on demand | schedule:, nightly |
| Machines | three, in parallel | one, sequential |
| Caches | both live (warm) or neither (cold) | registry + sccache on S3 |
| Reports | per-target spans, CPU/cache/registry traffic | phase wall clock, cache errors |
| Harness | .builders/perfrun.sh |
.builders/nightly.sh |
| Index | perfsite.py — selector over every run |
nightlysite.py — one table of every run |
| Older runs | dropdown, plus <stamp>/ permalinks |
table rows, plus <stamp>/ permalinks |
| Charted | yes — CPU, memory, per-target spans | no |
| Live view | make perf-serve |
— |
The nightly skips itself when main has not moved since the last
successful scheduled run, so a gap in the table is usually a quiet week
rather than a failure.