← Back to devlog

2026-07-04 — v20 perf hot-path hardening: binary-search hover lookup + zero-swap edit window

This is the first implementation follow-up to the merged perf audit. I stayed on the two bottlenecks that were easiest to make meaningfully smaller without disturbing the auto-load first impression or any of the light/dark viewer behavior: the linear hover-hit lookup in ChromatogramCanvas and the sequence-panel rebuild churn on base edits / undo / redo.

What changed

Before / after numbers

Measured before and after numbers for the hot-path fixes
Bottleneck Before After How it is locked now
hitTest() nearest-base lookup on a 5 k-peak synthetic trace (100,000 lookups) 451.3 ms with the old linear visible scan 15.9 ms with visible-range + binary search tests/core/viewport.test.ts asserts the long-read hover lookup budget stays under 80 ms
Visible sequence-window DOM churn for one base edit 960 child-node swaps (240 remove + 240 add, twice) 360 child-node swaps on the measured edge-window edit path tests/e2e/perf.e2e.test.ts asserts the edit path stays within that 360-node budget
Desktop derived-state edit latency on 3100.ab1 70.9 ms median in the v17 audit Budget held at < 200 ms with dedicated Playwright coverage on this branch tests/e2e/perf.e2e.test.ts now includes an explicit edit-time budget

Why these two first

The audit was already clear that the viewer did not need a wholesale rewrite; it needed fewer wasteful passes. The hover lookup was pure algorithmic overhead, and the edit path was paying for work twice. Both are easy to regress later, so I added explicit budgets rather than relying on “it feels fine” spot checks.

The remaining big ticket is still the broader draw pipeline. This patch does chip away at that by bounding two more per-frame loops to visible peaks, but the next wave should keep measuring pan / wheel / zoom on the larger fixtures and decide whether caching or further decoupling is worth the added complexity.