Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions bench/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@

1. **Library bundle size** — raw + gzipped bytes from `yarn build`'s `dist/` output. Catches accidental dependency bloat in shippable code.
2. **Lighthouse CI** — runs the demo (`yarn build:demo`, served by `vite preview`) against a fixed list of UniProt accessions. Captures LCP, TBT, CLS, Speed Index, and the overall Performance score.
3. **Custom milestones** — `bench/instrument.js` observes the host's DOM to mark `script-start`, `data-loaded` (loader removed), `first-render` (manager inserted), and `tracks-settled` (no subtree mutations for 250 ms — same quiescence pattern Playwright's `networkidle` uses). Lighthouse's user-timings audit captures these automatically, so they appear next to the headline metrics in `summary.md`.
3. **Custom milestones** — `<protvista-uniprot>` emits three `performance.mark()` calls at lifecycle transitions (`script-start` in `connectedCallback`, `data-loaded` after fetch resolves, `first-render` after Lit commits the manager to the DOM) plus three `performance.measure()` calls between them. Lighthouse's user-timings audit captures these automatically, so they appear next to the headline metrics in `summary.md`.

`fetch-and-parse` (script-start → data-loaded) and `render` (data-loaded → tracks-settled) are the per-stage breakdowns; `total` is the end-to-end. The `render` measure includes a constant ~250 ms quiescence gap, which cancels out in before/after comparisons.
`fetch-and-parse` (script-start → data-loaded), `render` (data-loaded → first-render), and `total` (script-start → first-render) are the durations surfaced in the report.

The custom layer is purely external: it only loads when the URL has `?bench=1`, observes the rendered DOM, and adds **zero changes to `src/`**. If you need finer-grained timings (e.g., per-track or per-adapter cost) later, add `performance.mark()` calls inside `src/` — but the milestones above usually suffice for spotting regressions in a refactor.
## Stability contract

The four mark/measure names — `protvista:script-start`, `protvista:data-loaded`, `protvista:first-render`, plus the three measures derived from them — are part of the component's public observable surface. **Renaming them, moving them to a different lifecycle point, or removing them is a breaking change for performance comparison.** A refactor that changes the conceptual meaning of any mark must update the corresponding baseline.

The marks fire unconditionally (every demo run, every consumer page) — they're cheap (~150 bytes shipped, no work when nobody is observing) and useful for any consumer that wants to profile.

## Run

Expand Down Expand Up @@ -61,7 +65,7 @@ yarn bench

## Comparing

Eyeballing two `summary.md` tables is enough most of the time. For a stricter check, LHCI's own diff works against the raw reports — see `lhci compare` docs.
Eyeballing two `summary.md` tables — current run vs. a committed baseline under `bench/baselines/` — is enough most of the time. For raw numbers, `jq` over `bench/results/lighthouse/manifest.json` pulls per-run metrics out of the latest run; `lhci open` will pop the current run's HTML reports in a browser if you want to see Lighthouse's full breakdown for one scenario.

Treat any single-metric delta under ~5% as noise unless it's consistent across all scenarios.

Expand All @@ -75,8 +79,9 @@ Scenarios are defined in `bench/lighthouserc.cjs` under `ci.collect.url`. Each q
| ------------------ | ----------------------------------------------------- |
| `lighthouserc.cjs` | LHCI config: scenarios, run count, throttling preset |
| `bundle-size.mjs` | Walks `dist/`, writes raw + gzip sizes per file |
| `instrument.js` | Browser-side marks; loaded only on `?bench=1` |
| `summarize.mjs` | Reads results, writes `summary.md` |
| `run.mjs` | One-shot driver (`yarn bench`) |
| `baselines/` | Committed snapshots — reference points for comparison |
| `results/` | Gitignored — output of the latest run |

The custom marks themselves live in `src/protvista-uniprot.ts`, not in this directory.
16 changes: 16 additions & 0 deletions bench/baselines/bundle-size-14632a3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"commit": "14632a30376b321fe98b2f33160a094e7dc55c08",
"shortSha": "14632a3",
"capturedAt": "2026-04-29T13:45:49.709Z",
"files": [
{
"file": "protvista-uniprot.mjs",
"raw": 4655449,
"gzip": 1162894
}
],
"total": {
"raw": 4655449,
"gzip": 1162894
}
}
16 changes: 0 additions & 16 deletions bench/baselines/bundle-size-4c80b07.json

This file was deleted.

28 changes: 28 additions & 0 deletions bench/baselines/summary-14632a3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Bench results

Captured: 2026-04-29T13:33:27.855Z
Commit: `14632a3`

Numeric cells show `median (min–max)`.

## Lighthouse (5 runs)

| Scenario | Perf | LCP | TBT | CLS | Speed Index |
|---|---|---|---|---|---|
| `accession=P05067` | 69 (38–70) | 5.5 s (5.5–5.8) | 22 ms (18–910) | 0.00 (0.00–0.00) | 2.1 s (2.0–2.9) |
| `accession=P38398` | 52 (45–53) | 46.4 s (46.2–46.7) | 266 ms (260–403) | 0.00 (0.00–0.00) | 4.2 s (3.7–4.6) |
| `accession=A0A2K5ULD0` | 80 (78–82) | 2.4 s (2.2–2.6) | 35 ms (16–42) | 0.00 (0.00–0.00) | 2.2 s (2.0–2.2) |

### Custom milestones (5 runs)

| Scenario | fetch-and-parse | render | total |
|---|---|---|---|
| `accession=P05067` | 1.7 s (1.6–2.3) | 7 ms (7–8) | 1.7 s (1.6–2.3) |
| `accession=P38398` | 5.2 s (4.3–5.8) | 7 ms (6–9) | 5.2 s (4.3–5.8) |
| `accession=A0A2K5ULD0` | 1.8 s (1.4–1.9) | 11 ms (9–12) | 1.8 s (1.5–1.9) |

## Bundle size (library, `dist/`)

| Total raw | Total gzip | Files |
|---|---|---|
| 4546.3 KB | 1135.6 KB | 1 |
28 changes: 0 additions & 28 deletions bench/baselines/summary-4c80b07.md

This file was deleted.

140 changes: 0 additions & 140 deletions bench/instrument.js

This file was deleted.

16 changes: 11 additions & 5 deletions bench/lighthouserc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@ module.exports = {
startServerCommand:
'npx vite preview --config vite.demo.config.mjs --port 4173 --strictPort',
startServerReadyPattern: 'Local:',
// `&bench=1` opts the page into bench/instrument.js, which emits
// `protvista:*` user timings that Lighthouse captures in its trace.
// The component emits `protvista:*` performance marks/measures
// unconditionally; Lighthouse captures them via its user-timings
// audit and `bench/summarize.mjs` surfaces them in summary.md.
url: [
// Well-annotated default — features, variants, structure.
'http://localhost:4173/?accession=P05067&bench=1',
'http://localhost:4173/?accession=P05067',
// Heavy entry — many variants, 3D Beacons.
'http://localhost:4173/?accession=P38398&bench=1',
'http://localhost:4173/?accession=P38398',
// Sparse entry — minimal feature load.
'http://localhost:4173/?accession=A0A2K5ULD0&bench=1',
'http://localhost:4173/?accession=A0A2K5ULD0',
],
// 5 runs per URL — LHCI takes the median, this smooths out the
// noise floor more than the default 3 without doubling wall time.
Expand All @@ -39,6 +40,11 @@ module.exports = {
// Be explicit so two machines on different Chrome versions still
// produce comparable numbers.
chromeFlags: '--headless=new --no-sandbox',
// Default is 45000 ms; the heavy variation payload on P38398
// sometimes runs right at that edge and Lighthouse marks the
// whole run as a page-load failure (Perf=0, all audits empty).
// 60 s gives those scenarios room to finish.
maxWaitForLoad: 60000,
},
},
upload: {
Expand Down
13 changes: 1 addition & 12 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,7 @@ export default [
},
},

/* Bench scripts — plain JS, not part of the shipped library. Browser
globals for the instrumentation, Node globals for the runners. */
{
files: ['bench/instrument.js'],
languageOptions: {
ecmaVersion: 2022,
sourceType: 'module',
globals: {
...globals.browser,
},
},
},
/* Bench runners — node scripts, not shipped. */
{
files: ['bench/**/*.{mjs,cjs}'],
languageOptions: {
Expand Down
4 changes: 0 additions & 4 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@
</head>

<body>
<!-- Bench instrumentation — no-op unless URL has ?bench=1 (guard is in
the script itself; we use a real src= so the build pipeline picks
it up — inline `<script type="module">` blocks get stripped). -->
<script type="module" src="./bench/instrument.js"></script>
<div>
<!-- Accession is read from ?accession= (default P05067). Used by the
bench/ workflow to swap scenarios without duplicating HTML. -->
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"build": "vite build",
"build:demo": "vite build --config vite.demo.config.mjs",
"start": "vite",
"test:lint": "eslint 'src/**/*.ts' 'bench/**/*.{js,mjs,cjs}'",
"test:lint": "eslint 'src/**/*.ts' 'bench/**/*.{mjs,cjs}'",
"test:types": "tsc",
"test:unit": "vitest run",
"test:watch": "vitest",
Expand Down
2 changes: 1 addition & 1 deletion src/filter-config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { VariationDatum } from '@nightingale-elements/nightingale-variation';
import { type VariationDatum } from '@nightingale-elements/nightingale-variation';
import { ClinicalSignificance } from '@nightingale-elements/nightingale-variation';

const scaleColors = {
Expand Down
Loading
Loading