* perf: optimize session loading and startup * fix(chat): stabilize history prepend virtualization * perf: unblock first session open from startup network contention Opening the first session after app start waited seconds for its message fetch. Three independent contributors, each measured via CDP network capture and Chromium net-log against the packaged desktop app: - The active-session watchdog fired an uncapped per-directory status poll and child-session discovery burst at startup, and other subsystems (git checks, global session pages, command/skill discovery) fanned out alongside it, saturating the browser's ~6 HTTP/1.1 sockets per origin. Add a shared background-network gate (concurrency 3) and route the watchdog, poll-shaped git reads (also priority: low), global session pages, command/skill loads, and the background update check through it. - The packaged renderer is cross-origin to the loopback backend, so every API call needs a CORS preflight; a few slow OpenCode-proxied requests held the whole pool while preflights and interactive traffic queued behind them. Lift Chromium's per-host connection cap for loopback via ignore-connections-limit in the Electron shell. - OpenCode initializes each directory lazily on its first request, so the first click paid that cost interactively. Warm the last-used directory and the three most recently opened projects right after OpenCode readiness, sequentially and best-effort, overlapping UI startup. Validation: new background-network tests, lifecycle warmup test, focused store/sync tests, UI type-check and lint, dead-code report, node --check plus electron type-check/lint, and CDP first-open measurements on the packaged app (message fetch socket queue 5.4s -> 0.03s). * fix(ui): keep interactive git reads out of background queue --------- Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
61 lines
3.1 KiB
Markdown
61 lines
3.1 KiB
Markdown
# Browser performance capture
|
|
|
|
Start OpenChamber locally, then run:
|
|
|
|
```bash
|
|
bun run profile:browser
|
|
```
|
|
|
|
The command opens an isolated Chrome profile. On the first run, complete any
|
|
login or setup in that window, prepare the sessions and screen you want to
|
|
measure, then return to the terminal and press Enter. Use OpenChamber normally
|
|
for the next 60 seconds.
|
|
|
|
Google Chrome is selected first on macOS, with Chrome Canary and Chromium as
|
|
fallbacks. Other Chromium-based browsers are used only when explicitly selected
|
|
with `--chrome /path/to/executable`.
|
|
|
|
The generated `artifacts/browser-profile-*/` directory contains:
|
|
|
|
- `summary.json`: long-task, memory, network, sync-operation, and UI streaming/render metrics. `failedRequests` includes transport failures and HTTP 4xx/5xx responses, while `httpErrorResponses` isolates HTTP errors;
|
|
- `trace.json`: import into Chrome DevTools Performance with **Load profile**;
|
|
- `network.har`: import into Chrome DevTools Network with **Import HAR**.
|
|
|
|
`summary.json.longTaskAttribution` correlates long tasks with global-session
|
|
lifecycle publications, session navigation, and targeted sidebar/message-list
|
|
renders. One task may appear under multiple marks when phases overlap.
|
|
|
|
Chrome trace finalization is allowed up to two minutes for large captures. If
|
|
Chrome still does not emit its completion event, the command preserves the
|
|
summary, HAR, and all trace events received so far instead of discarding the
|
|
entire recording. In that case `summary.json` sets `traceComplete` to `false`,
|
|
and trace-derived long-task totals should be treated as lower bounds.
|
|
|
|
Trace events are streamed to disk instead of being serialized into one large
|
|
JavaScript string. Summary and HAR files are written first, so they remain
|
|
available even if the trace file cannot be completed. `traceFileComplete`
|
|
reports whether `trace.json` finished writing.
|
|
|
|
The HAR omits response bodies and redacts cookies, authorization headers, and
|
|
sensitive URL parameters. The trace applies the same key and URL-parameter
|
|
redaction, but profiling artifacts can still reveal project paths and endpoint
|
|
names. Do not publish them without review.
|
|
|
|
`summary.json.sessionLoadPerformance.events` contains the bounded session-loading
|
|
operation timeline without runtime keys, directories, session IDs, message
|
|
content, or credentials. It includes recording-relative timing, caller, outcome,
|
|
retry count, and downloaded record count where available.
|
|
|
|
The capture bypasses the PWA service worker and reloads without the browser cache before recording, so repeated optimization runs execute the current local build instead of a previously cached bundle. By default, network recording begins after that preparation reload. Pass `--reload` to perform another cache-bypassing reload after recording starts and include startup requests in the HAR and session-load timeline.
|
|
|
|
Useful options:
|
|
|
|
```bash
|
|
bun run profile:browser -- --duration 120
|
|
bun run profile:browser -- --url http://localhost:4173
|
|
bun run profile:browser -- --output /tmp/openchamber-profile
|
|
bun run profile:browser -- --reload --no-prompt --duration 60
|
|
```
|
|
|
|
Run `bun run profile:browser -- --help` for all options.
|