Skip to content

list: batch dynamic height measurements - #330967

Merged
Connor Peet (connor4312) merged 4 commits into
mainfrom
connor4312/batch-list-dynamic-heights
Aug 18, 2026
Merged

list: batch dynamic height measurements#330967
Connor Peet (connor4312) merged 4 commits into
mainfrom
connor4312/batch-list-dynamic-heights

Conversation

@connor4312

@connor4312 Connor Peet (connor4312) commented Aug 14, 2026

Copy link
Copy Markdown
Member

Improves dynamic-height list rendering by batching DOM writes and reads and by
reusing measured rows that enter the final render range.

  • Groups height preparation, measurement, and publication into separate phases.
  • Promotes compatible measured rows instead of rendering the same element twice. (biggest win)
  • Releases unpromoted rows when rendering fails or the final range changes.
  • Validates row identity before promotion after reentrant list updates.
  • Adds tests for batching, row reuse, error cleanup, and reentrant splices.

Performance

Measured with DevTools traces while repeatedly alternating between the same small
and large chats. The samples form two non-overlapping modes. The baseline capture
contains 9 small-chat and 10 large-chat swaps; the after capture contains 11
small-chat and 12 large-chat swaps.

Overall interaction

Destination Metric Before median After median Change
Small chat Click handler 48.3 ms 33.3 ms -31.1%
Small chat Main task 51.0 ms 34.8 ms -31.9%
Small chat Thread CPU 47.8 ms 33.9 ms -29.1%
Large chat Click handler 291.5 ms 199.3 ms -31.6%
Large chat Main task 302.3 ms 204.4 ms -32.4%
Large chat Thread CPU 292.0 ms 197.2 ms -32.5%

The interquartile ranges do not overlap:

Destination Before p25-p75 After p25-p75
Small chat 43.9-54.3 ms 32.2-35.9 ms
Large chat 266.3-329.3 ms 195.3-204.3 ms

Small-chat pipeline

Stage Before median After median Change
setModel 13.2 ms 10.1 ms -23.7%
onDidChangeItems 7.4 ms 5.3 ms -28.6%
Refresh 3.6 ms 2.7 ms -26.4%
Rerender 4.0 ms 1.1 ms -71.8%
Dynamic-height probing 3.8 ms 0.8 ms -78.7%
setChildren 2.2 ms 1.5 ms -32.2%

Large-chat pipeline

Stage Before median After median Change
setModel 232.7 ms 160.1 ms -31.2%
onDidChangeItems 205.5 ms 140.7 ms -31.5%
Refresh 202.0 ms 137.7 ms -31.9%
Rerender 144.8 ms 95.4 ms -34.1%
Dynamic-height probing 93.3 ms 66.3 ms -29.0%
Row insertion 86.2 ms 53.0 ms -38.5%
Chat row rendering 94.3 ms 61.9 ms -34.3%
Chat content rendering 66.6 ms 43.8 ms -34.2%
setChildren 103.3 ms 58.6 ms -43.3%
Scroll to end 105.0 ms 79.0 ms -24.8%

Rendering and layout

Destination Metric Before median After median Change
Small chat Style recalculation count 11 5 -54.5%
Small chat Style recalculation time 12.4 ms 8.4 ms -32.5%
Small chat Layout count 10 4 -60.0%
Small chat Layout time 1.8 ms 0.9 ms -48.4%
Large chat Style recalculation count 19 13 -31.6%
Large chat Style recalculation time 92.0 ms 68.0 ms -26.1%
Large chat Layout count 18 12 -33.3%
Large chat Layout time 11.7 ms 7.4 ms -36.7%

Validation

  • npm run eslint -- src/vs/base/browser/ui/list/listView.ts src/vs/base/test/browser/ui/list/listView.test.ts
  • npm run typecheck-client
  • 10 targeted ListView and ChatListWidget tests
  • Independent safety reviews with Claude Opus 5 and GPT-5.6 Terra

(Commit message generated by Copilot)

Improves dynamic-height list rendering by batching DOM writes and reads and by
reusing measured rows that enter the final render range.

- Groups height preparation, measurement, and publication into separate phases.
- Promotes compatible measured rows instead of rendering the same element twice.
- Releases unpromoted rows when rendering fails or the final range changes.
- Validates row identity before promotion after reentrant list updates.
- Adds tests for batching, row reuse, error cleanup, and reentrant splices.
- Reduces median conversation-switch latency by 31.1% for a small chat and 31.6%
  for a large chat across repeated alternating swaps.

(Commit message generated by Copilot)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings August 14, 2026 21:40

Copilot AI 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.

Pull request overview

Optimizes dynamic-height list rendering by batching measurements and reusing measured rows.

Changes:

  • Separates DOM preparation, measurement, and publication phases.
  • Promotes compatible measured rows and cleans up retained rows safely.
  • Adds batching, cleanup, and reentrancy tests.
Show a summary per file
File Description
src/vs/base/browser/ui/list/listView.ts Implements batched measurement and row promotion.
src/vs/base/test/browser/ui/list/listView.test.ts Adds dynamic-height regression tests.

Review details

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

  • Files reviewed: 2/2 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment thread src/vs/base/browser/ui/list/listView.ts
Comment thread src/vs/base/test/browser/ui/list/listView.test.ts Outdated
roblourens
roblourens previously approved these changes Aug 14, 2026
Restart batched height measurement when renderer callbacks mutate the list, and cover multi-row batching and remove-all reentrancy.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@vs-code-engineering

vs-code-engineering Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

📬 CODENOTIFY

The following users are being notified based on files changed in this PR:

Benjamin Christopher Simmonds (@benibenj)

Matched files:

  • src/vs/base/browser/ui/list/listView.ts
  • src/vs/base/browser/ui/tree/abstractTree.ts

Comment thread src/vs/base/browser/ui/list/listView.ts
Comment thread src/vs/base/browser/ui/list/listView.ts
Comment thread src/vs/base/test/browser/ui/list/listView.test.ts Outdated
Keep surviving delegated measurements synchronized with the range map and prevent stale tree render cleanup from removing newer node mappings.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Return null for unmeasured delegated heights to satisfy the virtual delegate contract in CI type checking.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

6 participants