A 4x-CPU-throttled retrace (the honest weak-hardware proxy) surfaced
three residual per-frame costs; stack attribution pinned each:
- getParameters/getProgramCacheKey (~4% of main thread): every pooled
label sprite map swap set material.needsUpdate, bumping
material.version and forcing full program re-resolution next render.
Swapping between two non-null cached textures never changes the
compiled program (USE_MAP define unchanged) — new _setLabelMap()
helper only flags needsUpdate on a null<->texture transition, used at
all 7 swap sites.
- getBoundingClientRect (~1.2%): the 3D highway's per-frame canvas-size
self-check forced a layout read every frame. The CSS-box drift read
now runs every 10th frame (or when the wrap isn't pinned); the
backing-store comparison stays per-frame with cheap property reads
and forces an immediate box read + applySize when it fires.
- set textContent: the core 60 Hz HUD clock rewrote hud-time (and
getElementById'd it) every tick for a display that changes 1/s — now
write-on-change with a cached element ref.
(The remaining textContent writer in the trace is notedetect's
badges.js — external repo, to be filed there.)
tests/js: resize-reframe shape test updated for the hoisted _bsChanged
gate, incl. an assertion that the throttle can never delay the
backing-store path.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>