Skip to content

perf: reduce round-trips in browser command hot path#712

Merged
jackwener merged 1 commit intomainfrom
perf/reduce-roundtrips
Apr 2, 2026
Merged

perf: reduce round-trips in browser command hot path#712
jackwener merged 1 commit intomainfrom
perf/reduce-roundtrips

Conversation

@jackwener
Copy link
Copy Markdown
Owner

Summary

Four targeted optimizations to reduce latency in the browser command hot path:

  • Smarter eval retry delay (extension/src/cdp.ts): Reduced retry wait from fixed 1000ms to error-type-aware delays — 200ms for SPA navigation errors (which recover quickly), 500ms for debugger detach errors
  • Event-driven window readiness (extension/src/background.ts): Replaced fixed setTimeout(200) after chrome.windows.create() with tabs.onUpdated listener that resolves as soon as the tab reports status: 'complete' (500ms fallback cap)
  • Single /status call in bridge (src/browser/bridge.ts): Eliminated duplicate fetchDaemonStatus() calls in _ensureDaemon() — now makes one call and branches on extensionConnected vs daemon-running-but-no-extension
  • Stealth + settle coalescing (src/browser/page.ts): Combined two sequential sendCommand('exec', ...) round-trips (stealth injection + DOM settle) into a single eval, saving one full Node→daemon→extension→CDP round-trip per goto()

Test plan

  • tsc --noEmit passes clean
  • All 143 test files pass
  • Manual: verify goto() navigates and settles correctly with coalesced stealth+settle
  • Manual: verify window creation still works reliably without fixed delay

1. eval retry delay: 1000ms → 200ms for SPA navigation errors, 500ms
   for debugger detach. SPA navigations recover within ~100ms, the old
   1000ms delay was unnecessarily long.

2. Window creation: replace fixed 200ms sleep with tab-load poll.
   Listens for chrome.tabs.onUpdated status=complete with 500ms
   fallback cap. about:blank loads in ~20ms, saving ~180ms.

3. bridge.ts _ensureDaemon: single fetchDaemonStatus() call instead of
   two sequential calls (isExtensionConnected + isDaemonRunning both
   called fetchDaemonStatus independently). Saves one HTTP round-trip.

4. goto() post-navigation: coalesce stealth injection + DOM settle into
   a single exec call. Previously two sequential round-trips
   (Node→daemon→WS→extension→CDP each). Saves ~60-160ms per goto().
@jackwener jackwener merged commit 0c75ab3 into main Apr 2, 2026
12 of 14 checks passed
jackwener added a commit that referenced this pull request Apr 2, 2026
…sDaemonRunning

PR #712 refactored _ensureDaemon to use a single fetchDaemonStatus() call
instead of separate isDaemonRunning(). The test was still mocking the old
function, causing it to fall through to the spawn-daemon path and throw
the wrong error message.
jackwener added a commit that referenced this pull request Apr 2, 2026
…sDaemonRunning (#714)

PR #712 refactored _ensureDaemon to use a single fetchDaemonStatus() call
instead of separate isDaemonRunning(). The test was still mocking the old
function, causing it to fall through to the spawn-daemon path and throw
the wrong error message.
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.

1 participant