perf: eliminate always-on animations causing constant CPU/GPU load when idle#358
Open
psychosomat wants to merge 1 commit into
Open
perf: eliminate always-on animations causing constant CPU/GPU load when idle#358psychosomat wants to merge 1 commit into
psychosomat wants to merge 1 commit into
Conversation
- FAQDialog: remove infinite bounce/pulse on the trigger button and make decorative SVG spin/pulse animations hover-only. The bouncing container includes backdrop-blur and blur-xl layers, forcing expensive blur recomposition on every frame even when idle. - PreviewDock (MagicThread): replace the infinite framer-motion animation of 'top' (a layout property, JS-driven at 60fps) with a CSS keyframe animating transform/opacity, which runs entirely on the compositor. - EditorHeader: replace the infinite JS-driven framer-motion scale pulse on the backup status icon with the CSS animate-pulse utility. - globals.css: add the 'thread-travel' keyframes used by MagicThread.
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.
Problem
While using the app (especially the workbench page), CPU/GPU usage stays high even when the user is completely idle, causing fans to spin up and laptops to heat up. Profiling showed the cause is a set of decorative animations that run in infinite loops on every frame, regardless of user activity:
FAQ trigger button (
FAQDialog.tsx) — the worst offender. The button container runs an infinitebounceanimation while containingbackdrop-blur-mdandblur-xllayers. Because the blurred element moves every frame, the browser must recompute the blur filter continuously. On top of that, the SVG inside runs 4 infinitespinanimations, 2 infinitepulseanimations, and 3 SMIL<animate>loops simultaneously. SVG inner-element transforms are not compositor-accelerated, so these repaint on the CPU every frame.MagicThreadinPreviewDock.tsx— an infinite framer-motion animation of thetopproperty.topis a layout property, so this triggers a JS callback + style recalculation + layout on every frame (~60 fps), forever, on a page that is otherwise static.Backup status badge in
EditorHeader.tsx— an infinite JS-driven framer-motionscalepulse, keeping arequestAnimationFrameloop alive at all times when backup is not configured.Changes
FAQDialog.tsx: removed the always-on bounce/pulse on the trigger; all decorative SVG spin/pulse animations are nowgroup-hover:only, so the attention-grabbing motion still plays on hover but costs nothing when idle. Replaced the SMIL sparkle loops with static opacity (hover restores the pulse). Also addedaria-hiddento the decorative SVG (fixes a Biome a11y error).PreviewDock.tsx: replaced the framer-motiontopanimation with a CSS keyframe (thread-travel) animatingtransform/opacity— these run entirely on the compositor thread with no JS involvement and no layout work. The travel distance is passed via a CSS custom property, preserving the exact same visual.globals.css: added thethread-travelkeyframes.EditorHeader.tsx: replaced the infinite framer-motion scale loop with the CSSanimate-pulseutility (opacity-only, compositor-friendly), keeping the visual cue that backup is not configured.Rationale
transform/opacity). Infinite JS-driven animations and animations of layout properties (top) keep the main thread busy 100% of the time for purely cosmetic effects.backdrop-blur/bluris particularly expensive, as the blur must be re-resolved every frame.Testing
npx tsc --noEmitpasses for all touched files.