Skip to content

perf(staged): pause offscreen animations and drop static will-change from timeline rows#775

Merged
matt2e merged 2 commits into
mainfrom
slow-render
Jun 10, 2026
Merged

perf(staged): pause offscreen animations and drop static will-change from timeline rows#775
matt2e merged 2 commits into
mainfrom
slow-render

Conversation

@matt2e

@matt2e matt2e commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Pause per-frame wave and canvas animation loops (SineWave, GitTreeAnimation) when the elements aren't visible, avoiding wasted rAF work and rendering.
  • Remove the static will-change: transform from timeline rows (TimelineRow), which was forcing unnecessary compositing layers.

These changes reduce render/CPU overhead from animations and layout that aren't actively needed.

matt2e added 2 commits June 9, 2026 17:20
The static `will-change: transform` permanently promoted every
`.timeline-row` to its own GPU layer, forcing a backing store per row.
This is the source of the large ~1s "Composite" spike observed on
project switch in Staged.

The row has no transform animation or transition anywhere — it only
animates `background-color` on :hover — so the promotion is a no-op
that costs GPU memory and compositing work for no benefit. Removing it
leaves the hover transition working unchanged, with no composited layer.

Signed-off-by: Matt Toohey <contact@matttoohey.com>
These always-on requestAnimationFrame loops kept the compositor running
at ~60fps even when nothing visible was moving, keeping the layer tree
warm and worsening the project-switch render spike.

SineWave.svelte ran a rAF loop recomputing a 64-segment SVG path every
frame, once per running/building app across several views. Gate the loop
on document visibility (visibilitychange) and viewport intersection
(IntersectionObserver on the root <svg>) so it pauses while the tab is
hidden or the wave is scrolled off-screen, and resumes when visible. Also
reduce the path from 64 to 32 segments — overkill at the ~20px render
size — halving per-frame path work with no visible change.

GitTreeAnimation.svelte (splash) gets the same visibilitychange gating so
its canvas loop pauses while the document is hidden, resetting frame
timers on resume to avoid a dt jump. Existing onMount/onDestroy cleanup
is preserved.

Together these flatten the idle compositing baseline.

Signed-off-by: Matt Toohey <contact@matttoohey.com>
@matt2e matt2e requested review from baxen and wesbillman as code owners June 10, 2026 00:10
@matt2e matt2e merged commit 8f948a3 into main Jun 10, 2026
5 checks passed
@matt2e matt2e deleted the slow-render branch June 10, 2026 00:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant