Repository navigation
perf(native): cap looping animations at 30fps and hold them while unfocused - #1006
Merged
Merged
Conversation
…ocused A project tab's spinner and the Pulls busy ring asked for a frame at once, so a session busy outside the active project repainted the whole window at the display's rate. Spinner, BusyRing, the sidebar's busy ring and a running service's beat now share Theme.Loop: the next frame 33ms on, none while the window has no focus.
4 tasks done
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
With a session busy, lich-native held 44 to 78% of an RTX 3050 Laptop (
nvidia-smi pmon), and the compositor recomposited every frame. Two causes, both measured:ui.Spinner) and the Pulls busy ring (ui.Ring) asked for the next frame at once (op.InvalidateCmd{}), so a session busy outside the active project repainted the whole window at the display's refresh rate.Reset, so each frame re-strokes and re-uploads every path on screen and redraws the full surface. A pprof of the live window with three spinners: 26% of a core, 60% of it ingpu.Frame; the ring itself was 0.5%.What
Theme.Loop(gtx)asks for a looping animation's next frameui.LoopFrame(33ms) on.Spinner,BusyRing(renamed fromRing, which clashed with the palette'sRingcolor token, and now aThememethod likeSpinner), the sidebar card's busy ring and a running service's beat all go through it.Theme.Stillis set while the window has no focus (app.ConfigEvent): looping animations hold their frame and ask for none, and the beat skips its wake for the next pulse. Regaining focus asks for a frame.Measured
Nested headless umbriel on the same GPU, 1400x1420 window at 100Hz, one session busy in a project that is not the active tab:
The rig's window holds little content; the live window's per-frame cost is several times higher.
Not in this PR
Making a frame cost proportional to the ring's area needs partial redraw in the Gio fork's renderer (scissor, preserved back buffer, swap with damage, per backend) and stable op keys. Left for later.
Test plan
ui:TestLoopingAnimationsRedrawAt30fps(fails on the old immediate invalidate) andTestStillThemeHoldsTheFramecmd/lich-native:TestServiceBeatPacing, mid-pulse, at rest and stillnative/: gofmt,go vet ./...,go test ./...