Repository navigation
Commit c034e34
committed
perf(web): fetch snapshot geometry in one batch instead of one spawn per ref
`is visible`/`is hidden` and every interaction that aims by ref ask the web backend for the
bounds of every ref of a capture. The provider asked per ref, and each `agent-browser get box`
is a fresh Node process: measured on a 408-ref page, 381 spawns for one check. The budget they
spent on interpreter startup is why `is visible` on such a page died at the request envelope
(`ready timed out after 4500ms`) - the command answers in 90s against a 45s deadline. The
`--timeout` that would have raised the deadline is not even accepted by `is`/`wait`, so on a
big page those commands could not be made to work at all.
`batch` is the backend's own answer to that: it reads a JSON array of commands from stdin and
runs them inside ONE process, so the whole geometry pass is a bounded number of spawns - 200 refs
measure in 0.28s, all 408 of the bench page in 0.33s, against a 30s per-command budget. Getting
`stdin` to the spawn is the whole plumbing cost - `ExecOptions` already supported it, so
`runManagedAgentBrowser` forwards it and `runAgentBrowserCommand` passes it through.
Grouping lives with the grouping decision: the projection asks for the bounds of every ref it
published and the provider decides how many refs to send per call, because the refusal below is a
claim about the whole capture and only one owner sees all of it.
A ref the batch could not measure is an ordinary answer about that ref, and the entry's own
`success` decides that - never the error's wording. `isIgnorableBoxError` is gone with it: it
was a table of phrases the backend is free to reword, and a reworded one turned "this ref has no
box" into "geometry is broken", failing an interaction over a ref `is visible` never aimed at.
What the old code called a fatal error now has to be a fault of the batch as a whole, which is
what it actually reports: a whole-batch fault, or an answer that cannot be paired back to the
refs, is refused typed as `unusable batch result` with the reason named - the entry count, an entry
that carries no verdict (an object with neither `success` nor the command it answers would read as
"this element has no box" and drop a node silently), or an entry whose echoed command is not the
command that was sent. Position is trusted only as the order of the echoed command, never as the
pairing itself, because a mispaired box reads as a working capture with wrong geometry.
And a capture whose refs ALL went unmeasurable is refused rather than published: a hidden element
still measures as a box, so that shape means the backend answered to refs this snapshot does not
publish, and the tree would carry no addressable target with usable bounds. It is decided over the
capture rather than per group - a page whose first group went stale still answers for the rest. The
refusal reports
`reason: snapshot-refs-unmeasurable` with `requestedRefs` and `measuredRects`.
Tests: the geometry seam is its own file, `agent-browser-provider-rects.test.ts`, mirroring the
seam the provider source grew (the provider file was past the 1,000-line test tripwire and the
ratchet named this split as its fix); the provider file keeps the capture half. The old per-ref
tests became the batch contract: one call for the capture, groups bounded per fetch, a group that
answered nothing while a later one measured, entries refused by echoed command or missing verdict,
and each fault shape above.
Measured live (managed agent-browser 0.27.1, same page, base/head interleaved in one loop
iteration because this host sat at load 125-223, n=5 medians):
| page (refs) | command | this branch | before |
| --- | --- | --- | --- |
| index.html (408) | `is visible` | **5.9s** | **90.1s, and 3 of 5 runs refused outright** |
| index.html (408) | `fill` | **10.1s** | **90.2s** |
| light.html (8) | `is visible` | **2.5s** | 3.9s |
| light.html (8) | `fill` | 9.7s | 9.0s (noise; light pages were already fine) |
Backend spawns for one capture + geometry pass: **4 instead of 385** (408-ref page), 4 instead of
11 (8-ref page). Verdicts are unchanged: on a page with an on-screen button and one at
`top: -9000px`, both builds answer identically.
Closes #35161 parent 4adcae0 commit c034e34
6 files changed
Lines changed: 672 additions & 150 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
282 | 282 | | |
283 | 283 | | |
284 | 284 | | |
285 | | - | |
286 | | - | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
287 | 293 | | |
288 | 294 | | |
289 | 295 | | |
| |||
0 commit comments