Skip to content

perf: bring in upstream desktop and mobile performance fixes - #95

Merged
eyeveil merged 26 commits into
mainfrom
perf/upstream-picks
Nov 13, 2026
Merged

eyeveil merged 26 commits into
mainfrom
perf/upstream-picks

Conversation

@eyeveil

@eyeveil eyeveil commented Nov 13, 2026 •

Copy link
Copy Markdown
Collaborator

Why

Six open upstream performance PRs that merge cleanly on the fork, picked for the desktop app and the Android app. Each is brought in as a merge of its upstream branch, so the authors' commits and credit stay as they are upstream.

What changed

Scope

Left out for now: pingdotgg#35711 (idle session release), until its effect on Home is checked. pingdotgg#23601 was reverted once upstream and is unproven on a packaged desktop build here: the packaged-build check was stopped because its scratch app opened windows on the desktop. Watch for typing freezes or topology regressions in the next desktop build.

Verification

  • Typecheck of desktop, web, client-runtime, contracts and mobile passes.
  • Tests beside the changes pass: desktop 14, web 77, client-runtime 16.

Autofix with [code]smith
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.

juliusmarminge and others added 26 commits October 22, 2026 11:57
… sendSync

These tests reproduce pingdotgg#12689: every topology poll calls the
sendSync-backed bridge reads for bootstraps and local-environment
enabled, so a busy main process freezes the renderer while typing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every 3 s topology poll and every composer render called sendSync for the
local-environment bootstraps and enabled flag, so a busy main process froze
the renderer while typing (pingdotgg#12689).

The preload now reads each value synchronously once for the first paint and
caches it. The enabled flag only changes through a setter that relaunches the
app, so the startup value stays correct. Bootstraps are refreshed by a new
async bridge method over ipcRenderer.invoke on the same channel; the platform
poll awaits it before reading the primary and secondary topology, so a
WSL/secondary backend appearing, disappearing or changing still reaches the
UI within one poll.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…uilds the quiet list per changed thread

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…date

The quiet thread shell list read one quiet atom per thread, and each of those
read the whole thread index. Every shell frame re-ran all of them and rebuilt
the list once per changed thread, which froze the renderer for about a minute
when a thread opened with ~13k threads.

The list now builds from each enabled environment's threads and pending
subagent requests, the same way the other shell lists do. It holds shells
through streaming ticks itself, keyed by thread and pruned on every rebuild.

Fixes pingdotgg#25823

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replace the PR's single all-in-one navigation test with two focused tests
for pingdotgg#24651: navigation keeps its list and row identities through streaming
ticks while threadShellAtom follows live values, and changes a list shows
(count zero crossing, status, pending request, run stop, stopped thread's
timestamp) still rebuild it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ead shells

Derive navigationThreadShellsAtom from quietThreadShellsAtom instead of
comparing each row against the previous list's row at the same index. Rows
are now matched by thread key through the existing quietThreadShellAtom
family, so a streaming thread keeps its row when threads are inserted,
removed or reordered, and there is one streaming comparison site.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Building navigation from quietThreadShellsAtom mounts one per-thread atom for
every thread on mobile and measured 6-25x more derivation work per streaming
tick than main. The positional reuse costs what main costs, since unchanged
sources keep their cached shell and only changed rows are compared.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every keystroke in the composer re-rendered the whole footer (model picker,
controls menu and their popovers), because the runtime mode options were
rebuilt as a new array on each render. Since the managed policy hook was
called between deriving the modes and using them, React Compiler could not
memoize that derivation.

Call useManagedPolicy before the derivation so the compiler caches the mode
options on runtime mode, supported modes and policy. Typing 20 characters
drops from 542 to 293 component renders, and the render scenario now asserts
the footer re-renders only for the first character.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	apps/web/src/components/chat/ChatComposer.tsx
# Conflicts:
#	packages/client-runtime/src/state/threadShell.ts
# Conflicts:
#	apps/desktop/src/ipc/methods/window.ts
#	apps/desktop/src/preload.ts
#	packages/contracts/src/ipc.ts
…r main's preload changes

AI-assisted; verified with the tests and tools listed above.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Avoid forcing a separate desktop render to dock a draft composer before send.
Keep docking with the optimistic message updates; only real mobile view
transitions need a synchronous commit and an awaited update.

Co-authored-by: GPT 6.1 Sol <codex@openai.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Grok 4.7 <noreply@x.ai>
…s while the renderer polls topology (by juliusmarminge)
… no longer freezes with thousands of threads (by juliusmarminge)
…s the composer's footer controls (by OmarAlex24)
@github-actions github-actions Bot added vouch:trusted Author is trusted by repo permissions or the VOUCHED list. size:L labels Nov 13, 2026
@greptile-apps

greptile-apps Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The reviewed changes appear safe to merge.

Summary

This PR reduces repeated work in desktop connections, thread lists, and chat rendering.

  • Desktop topology polling refreshes asynchronously after its first cached read.
  • Thread lists keep their rows steady during streaming-only updates.
  • Finished Markdown blocks enter the shared cache after React commits them.
  • Mobile composer docking batches inline updates and commits transition updates right away.
  • Composer footer controls stop rerendering on every typed character.

No actionable issues were found.

Reviews (1) · Last reviewed commit: "Merge upstream pingdotgg/t3code#32323: p..." · Reviewed by Greptile

@eyeveil
eyeveil merged commit e39c48a into main Nov 13, 2026
33 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L vouch:trusted Author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants