Skip to content

perf(panel,ui): stop forcing a whole-window layout on every draw and DOM change - #4296

Merged
luke-agent[bot] merged 1 commit into
mainfrom
luke/panel-forced-layouts
Oct 21, 2026
Merged

luke-agent[bot] merged 1 commit into
mainfrom
luke/panel-forced-layouts

Conversation

@charleslpan

@charleslpan charleslpan commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Charles asked why Luke was slow and laggy today, then to fix the cheap 90/10 part. This PR is that part.

What the profile showed

I profiled Charles's panel renderer, built from main at 03b922186, while it ran.

  • Load: a task with a long agent transcript: about 53k DOM nodes, 30k of them the transcript's 531 messages.
  • Symptoms: the renderer used 1.4–2.2 GB of memory and spiked between 20% and 100% CPU.
  • Main thread: in 15 s it ran 379 style recalcs taking 3.1 s, plus 2.3 s of forced getBoundingClientRect.

About 21% of the main thread went to three synchronous layouts. Each one lays out the whole window:

Where Cost per 15 s Why
column-dock.ts 1.3 s A subtree MutationObserver re-measured every docked box after every DOM change under the shell, and re-observed every box each time. Since #4046 it also writes --column-dock on :root.
skill-picker.tsx (and the same code in mention-picker.tsx) 1.0 s It measured the composer's field during every draw of every composer, even with its list closed.
choice-bar.tsx 0.9 s useLayoutEffect had no dependency list, so the thumb was re-placed after every draw.

What changed

Left for later

These are the larger fixes, out of this PR's scope:

  • A transcript follow that doesn't restart from cursor zero.
  • Windowing the transcript.
  • The server-side GitHub re-reads.

Tests

  • ChoiceBar: the thumb follows a new choice, and an option removed ahead of it. This fails if the options key is dropped from the effect's dependencies.
  • column-dock: a to-do list landing over the composer raises the dock on the next frame. Frames are driven by the test.
  • applyMessagesPage: a page that repeats what is held keeps the held messages and the held array. This fails on the old join.

17 nearby test files (349 tests) pass, and the panel, ui and features typechecks pass. I ran no live before/after measurement on the Mac.

Made with Luke


Devin Review

View guided diff Turn on auto-fix

…DOM change

A profile of the panel on a long agent transcript (about 53k DOM nodes)
spent about 21% of the main thread in three synchronous layouts, each one
laying out the whole window:

- column-dock re-read every docked box after every DOM change under the
  shell, and re-observed every box each time. It now reads once per frame,
  follows the column and its parts afresh only when they change, and writes
  --column-dock on the root, and --floating-card, only when the value
  changes.
- The skill and mention pickers measured their field during every draw of
  every composer. They now measure only while their list is open.
- ChoiceBar re-placed its thumb after every draw. It now does so only when
  the choice or the options standing change; resizes stay with its
  ResizeObservers.

A transcript followed afresh is re-sent whole. applyMessagesPage now keeps
a message heard again unchanged, and answers what was held when a page
changes nothing, so the rows memoized on a message's identity skip the
redraw.

Co-authored-by: luke-agent[bot] <339870089+luke-agent[bot]@users.noreply.github.com>
@vercel

vercel Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
luke-web Ready Ready Preview Oct 20, 2026 11:50pm UTC

Request Review

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Devin Review

@luke-agent
luke-agent Bot added this pull request to the merge queue Oct 21, 2026
Merged via the queue into main with commit 4cabb4b Oct 21, 2026
12 checks passed
@luke-agent
luke-agent Bot deleted the luke/panel-forced-layouts branch October 21, 2026 00:07

This branch was successfully deployed

1 active deployment
Preview — 7e65aa31 Deployed Oct 20, 2026 by vercel[bot]
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