perf(detail): stop re-analyzing/re-decoding on every in-place photo switch#521
Merged
Conversation
…witch Devtools (6x CPU) showed the in-place detail view jank: opening blocked the main thread ~1.25s and each switch caused a ~68ms forced reflow plus a re-run of the histogram + tone analysis (network + CPU). Root causes and fixes: - HistogramChart / ToneAnalysis re-fetched the preview every switch via a `?_t=Date.now()` cache-buster and re-ran getImageData + a full-pixel scan. Removed the cache-buster (cross-origin CORS requests are cached separately from the grid's <img>, so the canvas still reads cleanly) and memoized the computed result per image url — revisiting a photo no longer recomputes. - Debounced the histogram/tone source: it now updates only after switching settles for ~220ms, so fast-swiping through many photos analyses just the one you stop on instead of every frame's photo. Initialised to the opened photo so it still shows immediately on open (no pop-in). - Thumbnail strip: the active thumbnail's scrollIntoView now runs in a rAF (instant, still centered) so it no longer forces a synchronous reflow on every switch, and the buttons use content-visibility:auto so off-screen thumbnails in a large album aren't laid out/painted on open. - Carousel placeholder slides only decode their real blurhash when near the current index; farther off-screen slides share one cached default decode, so opening a large album doesn't decode ~20 thumbhashes up front. Pure rendering/compute optimisation — no change to the LRU, the WebGL viewer lifecycle, or the data layer. Backdrop-blur on the strip left as-is (a visual call for @Zheaoli, tracked separately). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Pre-empts the unbounded-growth concern: the per-url histogram/tone caches are now bounded LRU (Map insertion order = LRU, re-set on hit keeps hot entries, evict the oldest past 256) so a long session over many distinct photos can't grow them without limit. Mirrors the decoded-blurhash cache. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Zheaoli
added a commit
that referenced
this pull request
Jun 12, 2026
…oesn't flicker ToneAnalysis returned a spinner unconditionally while `loading` (`if (loading) return <spinner>`), so every photo switch collapsed the whole tone section to a tiny spinner and re-expanded it when the new analysis finished. That shrink/grow shifted the entire info panel's layout (histogram and device-info rows below jumped up then back) — the "info panel flashes/ reloads on switch" the user reported. #532 added the `loading && !histogram` guard to the histogram chart but not to tone analysis, so the histogram stopped flickering while this one kept doing it. Apply the same guard here: only show the spinner on the first analysis (`loading && !toneData`); on a switch keep the previous tone values rendered until the new ones are computed (the in-session LRU cache from #521 still returns instantly for revisited photos). No size change → no panel shift. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
After the detail-view work deployed, opening a photo and switching between photos felt janky. Devtools profiling (6× CPU throttle to simulate a slower machine), corroborated by network-trace and code-read forensics:
Root cause = the new in-place switching re-runs per-photo work that the old full-page-nav detail only did once.
Fixes (pure rendering/compute — no LRU / WebGL-lifecycle / data-layer change)
?_t=Date.now()cache-buster in HistogramChart + ToneAnalysis. It re-fetched the cross-origin preview on every switch. Cross-origin CORS requests are cached separately from the grid's non-CORS<img>, so the canvas still reads cleanly — without the per-switch refetch.scrollIntoViewnow runs in arequestAnimationFrame(instant, still centered) → no forced synchronous reflow per switch; buttons getcontent-visibility:auto+contain-intrinsic-size→ off-screen thumbnails in a large album aren't laid out/painted on open.Backdrop-blur on the strip is left as-is — that's a visual change (frosted-glass look), tracked separately.
Verification
tsc+eslintclean for changed files. Profiled the current prod build to find the causes; the perf numbers are observational and want a post-deploy before/after re-measure via devtools (switch should no longer fire a preview fetch or histogram recompute except for the first analysis of a newly-settled photo; open decodes far fewer thumbhashes).