Parent: #475 (follow-up from the review of #476 — deliberately deferred, not a regression in that PR)
🔍 What
phaseTransitionThreshold = 0.01 (pkg/tui/springs.go:276) tests the spring's continuous parameter, but the only thing consumed downstream is lerpInt's integer output (pkg/tui/breakdownspring.go:90-92). The slide therefore keeps ticking long after the rendered height has stopped moving.
Measured on a 0→4 slide (67 ticks), height trajectory:
[0 ×6, 1 ×7, 2 ×8, 3 ×15, 4 ×31]
🔹 The height reaches its final value at tick 36 and never changes again — ticks 37–66 (45%) are pixel-identical
🔹 63 of 67 ticks (94%) render the same integer height as their predecessor
💸 Cost per redundant tick
| Work |
Time |
Alloc |
renderBreakdownFrame (bar mode) |
4.35 ms |
4.75 MB / 16,337 allocs |
renderBreakdownBox in View() (w=200) |
0.64 ms |
102 KB / 2,064 allocs |
A sequential swap is 134 ticks ≈ 2.2 s wall, ~660 ms CPU, ~640 MB allocation churn, of which ~127 ticks produce identical output — sustained ~30% of one core for the duration of every p↔m press.
🛠️ Proposed fix
Settle when lerpInt reaches breakdownSlideTo, and/or skip renderBreakdownFrame when the newly-lerped height equals the previous one. Safe because phase2Damping = 1.0 is critically damped — monotonic, no overshoot.
Expected: swap drops to ~74 ticks with byte-identical output.
⚠️ Notes
🔸 This predates the models panel (it is #416's slide behaviour); the sequential swap doubles the exposure, which is what surfaced it.
🔸 Endpoint-identity tests (TestProjectsSlide_EndpointIdentity_BarMode) must stay green — the whole point is that output is unchanged.
Parent: #475 (follow-up from the review of #476 — deliberately deferred, not a regression in that PR)
🔍 What
phaseTransitionThreshold = 0.01(pkg/tui/springs.go:276) tests the spring's continuous parameter, but the only thing consumed downstream islerpInt's integer output (pkg/tui/breakdownspring.go:90-92). The slide therefore keeps ticking long after the rendered height has stopped moving.Measured on a 0→4 slide (67 ticks), height trajectory:
🔹 The height reaches its final value at tick 36 and never changes again — ticks 37–66 (45%) are pixel-identical
🔹 63 of 67 ticks (94%) render the same integer height as their predecessor
💸 Cost per redundant tick
renderBreakdownFrame(bar mode)renderBreakdownBoxinView()(w=200)A sequential swap is 134 ticks ≈ 2.2 s wall, ~660 ms CPU, ~640 MB allocation churn, of which ~127 ticks produce identical output — sustained ~30% of one core for the duration of every
p↔mpress.🛠️ Proposed fix
Settle when
lerpIntreachesbreakdownSlideTo, and/or skiprenderBreakdownFramewhen the newly-lerped height equals the previous one. Safe becausephase2Damping = 1.0is critically damped — monotonic, no overshoot.Expected: swap drops to ~74 ticks with byte-identical output.
🔸 This predates the models panel (it is #416's slide behaviour); the sequential swap doubles the exposure, which is what surfaced it.
🔸 Endpoint-identity tests (
TestProjectsSlide_EndpointIdentity_BarMode) must stay green — the whole point is that output is unchanged.