Repository navigation
refactor: run every benchmark with strobe - #60880
Conversation
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.
There was a problem hiding this comment.
The port looks clean: type checks pass for the bench files in app (e2e tsconfig), core, ui, desktop and gui-plugins; the stability and playwright-config/theme-preload tests pass; and the core snapshot harness runs under plain Bun with the git process counts the description reports (2 for a no-change capture, 4 for 8 at once). I could not run any *.bench.ts end to end, because strobe 0.2.0 only ships a Windows x64 binary (strobe on Linux: "no build for linux-x64 is installed").
Public API: unchanged. Only dev-only package scripts (bench:*, test:bench*, root bench:devex), internal e2e helpers and the dev-only debug bar performance readouts are removed.
- macOS and Linux lose every benchmark. The removed tools (Playwright perf suite, core
benchmark-*,motion-bench.ts,bench-startup.ts) ran anywhere Bun or Playwright ran. Now none of the 57 cases runs off Windows, including the pure-Bun core and ui cases. Neither the perf README nor the desktop README says so, andstrobe.jsonlists a macOS exe path that can't be used yet. Please either keep a cross-platform way to run the script cases until strobe ships those builds, or state clearly that benchmarks are Windows-only for now (see inline). - Stale skill line.
.opencode/skills/app-e2e-tests/SKILL.md:57still saysmessageDelayexists for benchmarks (mock-server.ts:82), but this PR removes it. Agents following the skill will look for an option that no longer exists.
| per block and calls its exports. Both builds run the same harness: in a git ref's worktree strobe places this | ||
| checkout's copy, so its imports reach that build's code. | ||
|
|
||
| ## Run |
There was a problem hiding this comment.
strobe 0.2.0 only ships @hona/strobe-win32-x64, so every command below fails on macOS and Linux (no build for linux-x64 is installed), including the pure-Bun script cases in core and ui that used to run anywhere as bun script/benchmark-*.ts. Please say here, and in packages/desktop/README.md, that benchmarks need Windows x64 for now, or keep a way to run the script harnesses (snapshot.ts, location.ts, motion.ts) without strobe until it ships other platforms.
There was a problem hiding this comment.
Resolved by strobe 0.3.0, which this PR now pins. 0.3.0 ships macOS (arm64, x64) and Linux (x64, arm64) builds beside Windows x64 (@hona/strobe-darwin-arm64, -darwin-x64, -linux-x64, -linux-arm64). The root devDependencies list @hona/strobe too, so bunx strobe from the repository root runs the pinned build on every OS.
The script cases ran from the npm package on Linux and macOS (bun install --frozen-lockfile, then bunx strobe, no local strobe build):
Linux x64 (Debian 13 VM, 2 vCPU), e67bc51370:
$ bun packages/core/perf/snapshot.ts medium
$ bunx strobe bench packages/core/perf/snapshot.bench.ts --head . --check
10 of 10 cases passed
$ bunx strobe bench packages/core/perf/location.bench.ts --head . --check
4 of 4 cases passed
$ bunx strobe bench packages/core/perf/session.bench.ts --head . --check --params fixture=medium
2 of 2 cases passed
$ bunx strobe bench packages/ui/perf/motion.bench.ts --head . --check
1 of 1 cases passed
macOS arm64 (M4 MacBook Air, macOS 27), e67bc51370, fixture in the default temp folder:
$ bun packages/core/perf/snapshot.ts small
small: /private/var/folders/…/T/opencode-snapshot-bench/fixtures/small (2 s)
$ bunx strobe bench packages/core/perf/snapshot.bench.ts --head . --check --params fixture=small
10 of 10 cases passed
$ bunx strobe bench packages/ui/perf/motion.bench.ts --head . --check
1 of 1 cases passed
The macOS run found a bug in this PR, now fixed in a3719bc480. macOS's temp folder is a symlink (/var/folders is /private/var/folders). Snapshot compares a location with its worktree's real path, so a fixture generated under that symlink read as outside its own project, and every capture returned undefined. The harness now resolves the fixture root's real path.
Review point 2 (the stale messageDelay line in the e2e skill) was fixed in e825d74cc5.
What still differs by OS is now in packages/app/perf/README.md and packages/desktop/README.md. Script cases run the same everywhere. Page and desktop cases measure the most on Windows:
- On macOS and Linux, frames come from Chromium's trace only. OS present events (
--os-frames) are Windows only. - A software GPU is refused, so a VM or a server without a GPU cannot run page cases.
- macOS runs are not pinned to CPUs (macOS has no affinity API).
- On macOS, window pixels need the Screen Recording permission.
- On macOS, a desktop case launches only a build whose bundle id this account has never run. An isolated launch cannot move a Cocoa app's
~/Library, so strobe refuses rather than write into the user's own. - Linux finds windows through X11.
There was a problem hiding this comment.
Agreed, this is resolved at pr/head (e67bc5137).
-
0.3.0 is pinned: the root catalog in
package.jsonpins@hona/strobeto0.3.0. Inbun.lock, 0.3.0 lists optional builds for darwin-arm64, darwin-x64, linux-arm64, linux-x64 and win32-x64. -
It runs on Linux x64: I ran it here in a separate worktree of
pr/head(a Cloud Hypervisor VM).bun install --frozen-lockfileinstalled@hona/strobe-linux-x64@0.3.0. Then from the repository root:bunx strobe bench packages/ui/perf/motion.bench.ts --head . --checkpassed 1 of 1.bunx strobe bench packages/core/perf/location.bench.ts --head . --checkpassed 4 of 4.- strobe only warned that it was running in a VM, and the check passed anyway.
I didn't run snapshot or session here, and I didn't test on macOS.
-
The macOS fix looks right:
packages/core/perf/snapshot.ts:28now builds the fixture root withrealpathSync(base).location.ts:30already usedfs.realpath, so both harnesses get the real path for/var/folders→/private/var/folders. -
The docs cover the OS limits:
packages/app/perf/README.md:77-86lists them: Windows-only--os-frames, a software GPU refused, no CPU pinning on macOS, Screen Recording permission, X11 on Linux.packages/desktop/README.md:73covers the macOS bundle-id limit.
I didn't change anything in repo/. The shared checkout is a detached HEAD at e825d74cc, which is behind pr/head, and it has a bun.lock edit that isn't mine. I left both alone. The temporary worktree I used is removed.
…ng and the desktop app
core/perf (location, snapshot, session), ui/perf/motion and desktop/perf/startup replace core's benchmark-* scripts, ui's motion-bench, desktop's bench-startup and the e2e/devex dev-start suite. @hona/strobe-bench types the bench files, which every package typecheck now covers.
Page mocks keep the HTTP cache (fixtures/mock.ts); cases count history fetches, draft encodes and layout shift exactly; hover parks the pointer; Home and review sweep their larger sizes on request.
The snapshot cases then load at git refs whose session and model APIs differ.
Sessions in one project capture together; #59419 coalesced those captures (649 to 103 ms, 24 to 4 git processes on the medium fixture).
…became @hona/strobe is the SDK and the CLI launcher (bunx strobe runs the pinned version); @hona/strobe-bench is a deprecated alias. The perf README adds report --format pr for pull request tables.
0.3.0 ships builds for macOS (arm64, x64) and Linux (x64, arm64) beside Windows x64; bunfig.toml exempts every platform package from the release-age rule. The root devDependencies list it too, so bunx strobe runs the pinned version from the repository root, where every bench command runs.
… on macOS macOS's temp folder is a symlink (/var/folders is /private/var/folders). Snapshot compares a location with its worktree's real path, so a fixture generated there read as outside its own project and every capture returned undefined. The harness now resolves the fixture root's real path.
strobe 0.3.0 runs on Windows, macOS and Linux; script cases run the same everywhere, page and desktop cases measure the most on Windows.
There was a problem hiding this comment.
Benchmarks now run off Windows: on Linux, with strobe 0.3.0, the ui motion bench (1/1) and core snapshot bench (10/10) pass with --check, and the READMEs say what each OS supports. That covers my earlier point. The snapshot harness's real-path fix is correct. Public API unchanged. Nothing new to raise.
There was a problem hiding this comment.
This push only merges dev, and none of the PR's files change. The core snapshot bench still passes on Linux after #61546 (--check, 10/10). Thread 1 (Windows-only benchmarks) was already addressed by the strobe 0.3.0 bump and the per-OS notes. Public API unchanged. Nothing new to raise.
Every benchmark in the repo now runs with strobe. The app's Playwright harness, core's six
benchmark-*scripts, the UI motion script, the desktop startup script and the dev-startup suite are gone: −13,712 / +3,396 lines. 57 cases in 14*.bench.tsfiles cover their workloads. Each case compares two builds in pairs at normal speed, decides with an interval, refuses setups it cannot defend, and explains a move from one profiled run per side.Before → after
flowchart LR subgraph before["before: one harness per package"] A[app: Playwright fixture, BENCHMARK JSON,<br/>11 rAF probes, 12 percentile copies,<br/>7 CDP memory probes, 3 Vite fixture pages] C[core: 6 benchmark-* scripts,<br/>own timers, medians and JSON] U[ui: motion-bench.ts] D[desktop: bench-startup.ts log scraper,<br/>e2e/devex dev-start timer] end subgraph after["after: *.bench.ts beside the code"] AB[app/perf: 9 files] --> S CB[core/perf: location, snapshot, session] --> S UB[ui/perf: motion] --> S DB[desktop/perf: startup] --> S S[strobe: isolate, pair A/B, trace,<br/>decide, attribute, report] end before -. workloads ported .-> afterapp/perf/timeline.bench.tsapp/perf/stream.bench.tsapp/perf/tabs.bench.tsapp/perf/navigation.bench.tsapp/perf/home.bench.tsapp/perf/review.bench.tsapp/perf/diff.bench.tsapp/perf/composer.bench.tsapp/perf/desktop.bench.tsdesktop/perf/startup.bench.tsscript/bench-startup.ts,e2e/devexcore/perf/location.bench.tsbenchmark-location.ts,benchmark-location-memory.tscore/perf/snapshot.bench.tsbenchmark-snapshot.ts,-pack.ts,-worker.tscore/perf/session.bench.tsbenchmark-snapshot-session.tsui/perf/motion.bench.tsscript/motion-bench.tsThree kinds of case
untilends on what a person sees: strobe ignoresvisibility: hidden, and>>>reaches into the diff viewer's shadow root.mock(fixtures/mock.ts), so the browser's HTTP cache stays on and a case that reloads does not refetch every script. The e2e mock server runs unchanged.fixtures/events.ts) that never waits for the renderer.reset.Counted, compared exactly
net.requests{/api/session/*/message}net.requests{/api/session/*/message}count.draft.encodecount.draft.encodelayout.shiftcount.gitChecked against merged PRs
main.busymain.workmain.script−15%main.busyinteraction.p95main.work#59419 ("coalesce snapshot captures and skip repeat ignore work"), on core
strobe bench packages/core/perf/snapshot.bench.ts --base cdaba26fa5~1 --head cdaba26fa5, on the generated 20,000-file repo:count.git(exact)Why, for #60513 ("compute highlight styles once per subtree in Chromium")
Without reading the diff, strobe pins the win on style recalculation. Timed pairs, re-run with 8 pairs:
main.busy(primary)main.stylemain.scriptmain.layoutThe profiled launches say where: the same ~500 forced style recalcs per run, each cheaper.
Removed
e2e/performance,session-ui/performanceand their fixture pages; the dev debug bar's HUD (FPS, jank, long tasks, INP, CLS, heap, nav time;bar.tsx−480, 63 locales −1,350), whichstrobe record app:opencodemeasures from presented frames instead of rAF gaps. The bar keeps provider stats, the dev toggles, memory diagnostics and the Knobs.script/benchmark-{location,location-memory,snapshot,snapshot-pack,snapshot-session,snapshot-worker}.ts.script/motion-bench.ts. Desktop:script/bench-startup.ts. App:e2e/devex.bench:*package scripts, a search event only the benchmark dispatched (search-controller.ts),messageDelayin the mock server, a profile script that imported from another machine's worktree, and a stale test-speed log.Kept elsewhere
e2e/stability(bun run test:stability), a correctness suitetest-browser/theme-preload.test.ts,electron.vite.config.test.tscore/test/snapshot.test.tscore/test/git.test.tsSetup
@hona/strobe(catalog, 0.3.0) is a devDependency of the root, app, core, ui and desktop, for the bench files' types:typecheckandtypecheck:e2echeck every*.bench.ts. strobe runs its own embedded copy at run time. The package is also strobe's CLI launcher:bunx strobe …from the repository root runs the pinned build, one optional dependency per platform: Windows x64, macOS arm64 and x64, Linux x64 and arm64.bunfig.tomlexempts@hona/strobeand its five platform packages from the 3-day minimum release age, as it does other first-party packages.bunx strobe bench … --check: snapshot 10/10, location 4/4, session 2/2, motion 1/1 on Linux; snapshot 10/10, motion 1/1 on macOS). Page and desktop cases measure the most on Windows;packages/app/perf/README.mdlists what each OS gives.bun packages/core/perf/snapshot.ts medium opencode.Strobe gaps found here, all built
layout.shift--check, published typesprepare, CSS visibility, shadow DOM,main.workacross a page load