perf(chat): make session switching feel instant
Switching sessions ran as one synchronous commit: sidebar highlight, URL, a full timeline remount with markdown re-parse, and around nine requests, so nothing changed on screen for 150-250ms after the click. - ChatContainer swaps the timeline on a deferred copy of the selection, so the active row, URL, and tab commit first and the timeline renders behind them; selection policy keeps reading the live store value. - The message fetch starts before the selection is published. - Sidebar rows stop re-rendering on a project switch: directory-scoped sync hooks read the runtime context and a subscribable current-directory source instead of the directory-bearing context; the grouping builder reads git branches through a ref and section caches key the branches they use; descendant ids are keyed by content. Rows per switch went from 73 to 8. - Markdown skips the async re-render when the settled cached blocks are already painted, and mounts synchronously once its lazy module is loaded; the module is preloaded at boot. - A timeline reveal gate holds a freshly opened session at opacity 0 while any provisional markdown paint catches up (250ms cap), then fades the whole timeline in once, so text, tools, and recap appear together. - Switch fan-out trimmed: knowledge summary deduped, MCP status refreshed only when stale, non-repo directories cached by the git repo check, OpenChamber defaults cached briefly, agent memory reused for the same project, goal text cached, PWA manifest rebuilt after the switch settles. - Header tabs snap into the active state and keep the title at the same height in both states. - Prefetch on row press; composer focus moved off the commit. `bun run profile:switch` records ack/content latency, longest task, and requests per switch, cold and warm, and compares runs against a baseline. Measured warm switch: ack 228ms to about 40-60ms, content 228ms to about 100-120ms.
This commit is contained in:
@@ -12,6 +12,7 @@ or extending these scripts. The methodology rules they enforce come from
|
||||
| `bun run profile:idle` | What the app does while nobody interacts with it. |
|
||||
| `bun run profile:session` | What receiving and rendering a live assistant response costs. |
|
||||
| `bun run profile:animation` | What a CSS animation costs, isolated from the app. |
|
||||
| `bun run profile:switch` | How long switching sessions from the sidebar takes, cold and warm. |
|
||||
| `bun run profile:browser` | A manually driven capture, for interactions that cannot be scripted. |
|
||||
|
||||
All of them measure a real browser over CDP. Pass `--help` to any of them for
|
||||
@@ -106,6 +107,30 @@ top. Note that `rotate: 360deg` is *not* equivalent to
|
||||
Add a variant to `animation-fixture.html` to measure a property or technique
|
||||
that is not listed.
|
||||
|
||||
## profile:switch
|
||||
|
||||
Clicks sidebar session rows with real mouse input and measures, per click, the
|
||||
two moments a user feels: `ack`, when the clicked row is highlighted as active
|
||||
(the first visible reaction), and `content`, when the timeline shows messages
|
||||
that were not on screen before. It also reports the longest main-thread task
|
||||
inside each switch and every request the switch triggered, so fan-out
|
||||
regressions show up next to the latency they cause.
|
||||
|
||||
Every session in the plan is visited twice. The first visit is usually cold
|
||||
(a network round trip for messages); the second is warm, served from the
|
||||
in-memory session store. They have different budgets and are reported
|
||||
separately.
|
||||
|
||||
```bash
|
||||
bun run profile:switch -- --url http://127.0.0.1:4599 --output artifacts/switch-before
|
||||
bun run profile:switch -- --url http://127.0.0.1:4599 --baseline artifacts/switch-before --budget-ack 32 --budget-content 100
|
||||
```
|
||||
|
||||
`--sessions a,b,c` picks the rows to click; the default is the first rows in
|
||||
the sidebar, so pass explicit ids to compare runs across days. The row must be
|
||||
present in the sidebar; the command fails rather than measuring a click on
|
||||
nothing.
|
||||
|
||||
## Reading The Results
|
||||
|
||||
Every run writes a JSON summary next to any raw capture, so results can be
|
||||
|
||||
Reference in New Issue
Block a user