Deduplicate initial resources by request URL rather than by file, so a file referenced twice with different query strings is counted twice, as the browser fetches it; fragments are still ignored. Each resource now carries both its file path and its request URL. Describe the CI ratchet as the goal of the loop rather than as existing enforcement until the baseline and job PRs merge. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
3.5 KiB
Performance journeys and the CI ratchet
IPTVnator measures performance through a small set of everyday user journeys.
Each journey has deterministic counters that are asserted exactly, and
wall-clock timings that are recorded as evidence. Counters are meant to be
ratcheted in CI: a committed baseline that may only be lowered, and only with
the measured output as evidence. This document is the contract for that loop;
tools/performance/ holds the scripts. The measurement script lands first;
the baseline file and the CI job follow in their own PRs (#1693, #1694), so
until they merge the reported number is informational, not enforced.
Journeys
| Journey | Start | End |
|---|---|---|
J1 launch |
Electron process spawn | first playlist or portal card rendered on /workspace, inline splash removed |
J2 open-source |
click on a portal card | live category list and first channel page painted |
J3 playback |
click on a channel | HTML5 playing event |
J4 search |
six-character query typed into global search | results list settled |
Only the J1 counter renderer.initialBytes is instrumented today. The other
journeys and counters follow the plan in .plans/ and are added one thread at
a time; each thread names its journey and counter in the PR description.
renderer.initialBytes
The bytes a browser fetches before Angular can bootstrap, read from the built
dist/apps/web/index.html:
index.htmlitself,- every same-origin
<script src>, includingassets/app-config.js, - every
<link rel="stylesheet">, - every
<link rel="modulepreload">chunk.
Manifest, icons, external URLs and lazy chunks are not counted. A file that
index.html references but the build did not emit is an error, never zero
bytes. The value is raw (uncompressed) size, which is what the renderer parses;
it matches the "Initial total" line of the Angular build output.
pnpm nx build web # production configuration
pnpm run perf:initial-bytes # human-readable breakdown
pnpm run perf:initial-bytes -- --json # machine-readable breakdown
pnpm run perf:initial-bytes -- --summary dist/performance/journey-summary.json
--summary writes the journey summary shape (journeys.<journey>.counters)
that the ratchet checker consumes. --dist <dir> points the script at another
build output, for example the electron-performance configuration.
The measurement script is tools/performance/measure-initial-bytes.mjs; its
Node tests run with pnpm nx test performance-tools (Tier B in the coverage
policy) and lint with pnpm nx lint performance-tools.
Adding a counter
- Produce the value from the built output or from a deterministic probe, not from source heuristics. Missing inputs must fail the measurement.
- Emit it under
journeys.<journey>.counters.<name>in the summary JSON. - Cover the extraction and the failure modes with
node --testand register the test file intools/performance/project.json. - Validate the counter before it becomes a guardrail: one PR must show that lowering it moved wall-clock in the same journey.