Skip to content

🤖 perf: stop New Workspace creation controls re-rendering per keystroke - #5938

Merged
ThomasK33 merged 3 commits into
mainfrom
perf/5937-creation-controls-rerender
Oct 9, 2026
Merged

ThomasK33 merged 3 commits into
mainfrom
perf/5937-creation-controls-rerender

Conversation

@ThomasK33

@ThomasK33 ThomasK33 commented Oct 9, 2026 •

Copy link
Copy Markdown
Member

Summary

Since #5916, the New Workspace composer re-renders its creation controls on every keystroke. The nightly Perf Profiles test "perf: type in the New Workspace composer" allows at most 1 render and saw 165. This PR moves the pure default-runtime derivation in useDraftWorkspaceSettings below the hook's last hook call. React Compiler then caches it, and the controls stop re-rendering while you type.

Fixes #5937

Cause

src/browser/hooks/useDraftWorkspaceSettings.ts:404-418 on main (9554bb4):

  1. 🤖 refactor: keep preferences and workspace AI picks on the server #5916 replaced useState(() => defaultRuntime) with selectedRuntime = runtimePick ?? defaultRuntime (line 418), so the selection follows defaults that load after mount.
  2. defaultRuntime = buildRuntimeForMode(...) (line 404) runs before the hook's later useState, useRef and useEffect calls. In that layout React Compiler does not cache it: the compiled output calls buildRuntimeForMode on every render.
  3. Until the user picks a runtime, selectedRuntime is a new object on every render. setSelectedRuntime uses it, so the setter is new on every render too.
  4. Both reach CreationControls through useCreationWorkspace and ChatInput/index.tsx (selectedRuntime, onSelectedRuntimeChange), so each typed character re-rendered the controls.

A temporary prop-diff log on a dev server (removed) showed only selectedRuntime and onSelectedRuntimeChange changing per keystroke, plus two fields that CreationControls rebuilds or does not read.

Fix

Build defaultRuntime and selectedRuntime after the last hook call (now line 451). Hook order is unchanged, and both values are read only after they are built. The PR adds no manual useMemo, useCallback or React.memo. #5916's behavior stays: preferences and workspace AI picks live on the server, defaults that arrive after mount still apply, and a live Settings change still replaces a pick. The comment at the moved code names the test that guards the identity: this placement is not a permanent memoization guarantee.

Product LoC: 31 (+17 / -14), in one file.

Tests

Commit 1 adds useDraftWorkspaceSettings.compiler.test.tsx (a later test-only commit switches it to the declared @babel/preset-env, and the three results below were rerun with that version). Bun and Jest load the hook without React Compiler, so a plain render test cannot see this bug. The new test compiles the real hook source with the shared src/vite/reactCompilerConfig, evaluates it with a require bound to the hook's path (same React, stores and contexts), renders it through React, and re-renders with only an unrelated prop changed. It asserts that selectedRuntime and setSelectedRuntime keep their identity. It does not inspect compiled code or cache slots, and it changes no global Jest, Babel or Bun config. check-test-routing routes it to the Bun unit lane.

Hook source Result
origin/main 9554bb4e4f (merge base) 0 pass 1 fail (toBe on selectedRuntime: "Received: serializes to the same string")
main with #5916's selectedRuntime hunk reverted (scratch) 1 pass 0 fail
this PR 1 pass 0 fail

Commit 1 also adds "a live Settings default runtime change replaces an explicit pick". It passes on main, and it fails when I disable the effect that applies the Settings change. The existing tests for late-arriving defaults ("applies remembered runtime options that load after mount") and explicit picks still pass (12/12).

Validation

  • make static-check, make check-startup-imports and the sibling tests pass. make check-react-compiler: "23/24 hot components compile (1 known skipped)".
  • useCreationWorkspace.test.tsx has 3 order-dependent failures in a full-file run locally. They fail the same way on origin/main and pass when run alone. This PR does not touch that file.
  • Dogfood on a loopback dev server (env -i, XUM_DISABLE_TELEMETRY=1, temp XUM_ROOT): the chat-input.creation-controls marker recorded 13 renders for 11 typed characters on main and 0 with the fix (auto-naming off; with auto-naming on, 2 renders came from the generated name). The runtime select (Worktree → Local), the branch select (main → feature-x) and the auto-naming toggle work, and typing after those picks recorded 0 renders. Screenshots at 1200 px and 390 px are below.

Perf Profiles dispatch 37921214088 (perf_profiles=small) on the final head 250f27ace3: success, 9 passed, 0 failed. "perf: type in the New Workspace composer" passed. The earlier dispatch 37914713834 on 885281161e also passed. The head changed after it, so it was rerun.

Run creation-controls renders while typing workspace-open-small RecalcStyleCount (info only)
Dispatch 37909222999 at 58b5ea91d0 (before #5916) 0 58
Nightly 37907425111 at 9554bb4e4f (main) 165, 167 66
Dispatch 37914713834 at 885281161e (this PR, earlier head) 0 70
Dispatch 37921214088 at 250f27ace3 (this PR, final head) 0 73

RecalcStyleCount is from each run's perf-summary.json, one sample per run. This PR does not target it, and two samples are not enough to call a trend.

New Workspace composer at 1200 px after runtime, branch and auto-naming changes

New Workspace composer at 390 px


Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: high • Cost: $7.86

Compiles the real useDraftWorkspaceSettings source with the shared
reactCompilerConfig and checks that selectedRuntime and setSelectedRuntime
keep their identity across unrelated re-renders (#5937). Fails on main.

Also covers a live Settings default runtime change replacing an explicit pick.

_Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking: `high`_
Build the pure default runtime after the hook's last hook call. Built before
the later useState/useRef/useEffect calls, React Compiler left it uncached, so
with no runtime pick selectedRuntime and setSelectedRuntime were new on every
render and CreationControls re-rendered per typed character (#5937).

_Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking: `high`_
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-09T11:03:38.970446Z 250f27a Manual request
🔒 Security Review ✅ Completed 2026-10-09T11:05:24.970897Z 250f27a Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

The compiler test loaded @babel/plugin-transform-modules-commonjs, which
package.json does not declare. Use @babel/preset-env (declared, same module
output as babel.config.js) instead.

_Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking: `high`_
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

Round 2: the only change since your last review is a test-only commit. The compiler test now uses the declared @babel/preset-env instead of the undeclared @babel/plugin-transform-modules-commonjs.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. You're on a roll.

Reviewed commit: 250f27ace3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 250f27ace3

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@ThomasK33
ThomasK33 added this pull request to the merge queue Oct 9, 2026
Merged via the queue into main with commit b534f5a Oct 9, 2026
35 checks passed
@ThomasK33
ThomasK33 deleted the perf/5937-creation-controls-rerender branch October 9, 2026 11:26
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.

🤖 perf: New Workspace composer re-renders its creation controls on every keystroke since #5916

1 participant