Skip to content

Speed up snapshots of large pages - #2509

Open
ctate wants to merge 2 commits into
mainfrom
ctate/speed-up-snapshots-04a736
Open

ctate wants to merge 2 commits into
mainfrom
ctate/speed-up-snapshots-04a736

Conversation

@ctate

@ctate ctate commented Nov 9, 2026

Copy link
Copy Markdown
Collaborator
  • Read the Accessibility.getFullAXTree response directly into the typed struct instead of through an intermediate JSON value, so multi megabyte responses are parsed once.
  • Track compact snapshot ancestors with a stack, which keeps --compact linear on large tables.
  • Output, including refs, is unchanged.

Snapshot of a large table spends most of its time in
Accessibility.getFullAXTree: Chrome serializes the whole tree, 5.7 MB and
13,033 nodes for a 500 row table. The client then parsed that payload twice,
once into a serde_json::Value in the reader and again into the typed struct.

Responses that a caller registered for raw delivery now skip the Value parse.
The reader reads the leading "id" of the frame, which is available before the
payload, and hands the text to the waiting send_command_typed_raw caller.
Frames that do not lead with an id, malformed frames and lone surrogate
escapes go through the same handling as the shared reader.

compact_tree marked ancestors by walking back over every earlier line for each
kept line, which is quadratic in the number of snapshot lines and cost 3.5 s on
a 2,000 row table. It now keeps the open ancestors on a stack.

A 500 row snapshot goes from 730 ms to 575 ms median wall time and a 2,000 row
one from 3,110 ms to 2,519 ms; with --compact the 2,000 row page goes from
6,618 ms to 2,550 ms. Snapshot output, including refs, is byte identical on all
fixtures in all modes.
@vercel

vercel Bot commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
agent-browser Ready Ready Preview, v0 Nov 10, 2026 1:46am UTC
agent-browser-env-demo Ready Ready Preview, v0 Nov 10, 2026 1:46am UTC

let _ = self.socket.shutdown(Shutdown::Both);
Self::abort_task(&self.reader_handle).await;
self.pending.lock().await.clear();
self.raw_pending.lock().await.clear();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if we add lifecycle tests for send_command_typed_raw too? the existing close test only exercises pending, so a regression in raw_pending cleanup could leave snapshots waiting for the 30-second timeout without failing that test. i checked close, reader EOF, cancellation and post-close rejection with temporary probes and they all passed; keeping those cases in the suite would guard that behavior.

This branch was successfully deployed

2 active deployments
Preview – agent-browser — 41e5bf4b Deployed Nov 10, 2026 by vercel[bot]
Preview – agent-browser-env-demo — 41e5bf4b Deployed Nov 10, 2026 by vercel[bot]
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.

2 participants