Skip to content

perf(web): switching threads no longer re-renders the outgoing thread's rows - #21123

Merged
juliusmarminge merged 1 commit into
mainfrom
perf/switch-old-rows-context
Oct 18, 2026
Merged

juliusmarminge merged 1 commit into
mainfrom
perf/switch-old-rows-context

Conversation

@juliusmarminge

Copy link
Copy Markdown
Member

Switching threads re-rendered the outgoing thread's visible rows one last time, with the incoming thread's context, right before they unmounted. TimelineRowCtx wrapped the whole LegendList. On a switch, MessagesTimeline renders with the new thread's routeThreadKey, threadRef, markdownCwd, workspaceRoot and skills. LegendList only swaps its containers to the new rows a commit later (in a layout effect). So in the switch commit every mounted row of the old thread saw a new context value, and every ChatMarkdown got a new cwd/threadRef/skills. That re-rendered all of its paragraphs, list items, code spans and SkillInlineText for content that was about to disappear.

The provider now sits inside renderItem, so each row gets the context through its container. A row only sees a new value when LegendList re-renders that row. extraData now includes sharedState, so rows that stay mounted still pick up a changed value, the same way they already did for a list identity change.

Measurement

The thread-switch scenario from the web perf before/after report: 3 seeded threads (2,662 / 149 / 45 messages), switched L→M→S x3 with 2 s each. Production build (vp build --minify false), served by the worktree's own server (no --watch), headless Chromium 1600x1000, renders counted by a fiber probe that skips bailed-out subtrees. Base and fix were built from the same main (ea97e8ba31) and alternated per run.

main this PR Δ
Renders (median of 3) 15,892 13,970 −12%
Commits 212 208 —
runs 16,070 / 15,892 / 15,887 13,970 / 14,061 / 13,767
SkillInlineText 1,116 677 −39%
MarkdownParagraph 335 197 −41%
MarkdownListItem 279 174 −38%
MarkdownCode 205 115 −44%
ChatMarkdown 128 <113 (out of top 25)
TooltipTrigger 1,412 1,214 −14%

What's left in the markdown counts is mounting: the new thread's rows that come into view. That work is needed. Most of the other ~14k renders are outside the timeline (header, sidebar, composer, popovers).

Claude Opus 5.5 via Claude Code.

🤖 Generated with Claude Code

…'s rows

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Oct 18, 2026
@juliusmarminge juliusmarminge added the macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews label Oct 18, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 18, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 39be05f

Macroscope's review found this PR approvable — This single-file change narrowly adjusts timeline context propagation so outgoing thread rows avoid an unnecessary final render while mounted rows still receive updated shared state. It introduces no new capability, schema or API changes, deployment changes, product-default changes, or static-analysis overrides.

You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Oct 18, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Path: .coderabbit.config.ts
  • Review profile: CHILL
  • Plan: Team
  • Run ID: 5d5ff1b4-29d3-4f94-a051-bf1d2487d61d
📥 Commits

Reviewing files that changed from the base of the PR and between d0918f1 and 39be05f.

📒 Files selected for processing: 1
  • apps/web/src/components/chat/MessagesTimeline.tsx

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 5 remain after this review.

📝 Walkthrough

The timeline now provides TimelineRowCtx within each rendered row. TimelineRowActivityCtx wraps the viewport and its contents. LegendList.extraData now includes the list identity, row count, and shared state.

Changes: Timeline Context Updates

Layer / File(s) Summary
Timeline context scope
apps/web/src/components/chat/MessagesTimeline.tsx
Each rendered row receives its own TimelineRowCtx provider. TimelineRowActivityCtx wraps the viewport and its contents. LegendList.extraData includes the list identity, row count, and shared state.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Refactor

Suggested reviewers: maria-rcks

Merge Risk: ⚪ Minimal · up to 39be0

The timeline context change is ready to merge after normal checks; no actionable risk remains.

Pre-merge checks: Passed 3 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Description check Warning The description explains the problem, implementation, performance measurement, and agent attribution. It does not include the required Scope and approval section, and it does not provide the required … Add a Scope and approval section with the related issue or explicit maintainer approval, or explain why this focused fix qualifies for an exemption. Add before/after screenshots for the UI change, plus a short recording if interaction timin…
Passed Passed checks: 3 passed
Check name Status Explanation
Title check Passed The title clearly and concisely describes the main performance fix: preventing unnecessary re-renders when switching threads.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description explains the problem, implementation, performance measurement, and agent attribution. It does not include the required Scope and approval section, and it does not provide the required UI before/after screenshots or explain why screenshots are unavailable.

Resolution

Add a Scope and approval section with the related issue or explicit maintainer approval, or explain why this focused fix qualifies for an exemption. Add before/after screenshots for the UI change, plus a short recording if interaction timing is relevant, or state clearly what verification evidence could not be provided.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@juliusmarminge
juliusmarminge merged commit 91ec4be into main Oct 18, 2026
33 checks passed
@juliusmarminge
juliusmarminge deleted the perf/switch-old-rows-context branch October 18, 2026 09:12
rahil-patel-21 added a commit to rahil-patel-21/t3code that referenced this pull request Oct 18, 2026
Resolved the MessagesTimeline conflict by taking upstream's per-row context
provider (pingdotgg#21123) while keeping this branch's removal of the timeline minimap.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
github-actions Bot added a commit to omarcresp/t3code-flake that referenced this pull request Oct 18, 2026
## What's Changed
* perf(web): switching threads no longer re-renders the chat view for an unchanged preview list by @juliusmarminge in pingdotgg/t3code#21130
* fix(server): opening a large database no longer blocks startup for minutes by @t3dotgg in pingdotgg/t3code#21122
* perf(web): switching threads no longer re-renders the outgoing thread's rows by @juliusmarminge in pingdotgg/t3code#21123
* perf(web): reasoning rows skip the tool-failure text scan by @juliusmarminge in pingdotgg/t3code#21146
* perf(web): pull request chains parse each link's URL once by @juliusmarminge in pingdotgg/t3code#21147


**Full Changelog**: pingdotgg/t3code@v0.1.1-nightly.20261018.3302...v0.1.1-nightly.20261018.3315

Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.1.1-nightly.20261018.3315
github-actions Bot added a commit to davidvanderklay/t3code-flake that referenced this pull request Oct 18, 2026
## What's Changed
* perf(web): switching threads no longer re-renders the chat view for an unchanged preview list by @juliusmarminge in pingdotgg/t3code#21130
* fix(server): opening a large database no longer blocks startup for minutes by @t3dotgg in pingdotgg/t3code#21122
* perf(web): switching threads no longer re-renders the outgoing thread's rows by @juliusmarminge in pingdotgg/t3code#21123
* perf(web): reasoning rows skip the tool-failure text scan by @juliusmarminge in pingdotgg/t3code#21146
* perf(web): pull request chains parse each link's URL once by @juliusmarminge in pingdotgg/t3code#21147


**Full Changelog**: pingdotgg/t3code@v0.1.1-nightly.20261018.3302...v0.1.1-nightly.20261018.3315

Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.1.1-nightly.20261018.3315
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews size:S 10-29 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant