Repository navigation
🤖 perf: desktop cold-start A/B runner and dispatch job - #5997
Merged
Merged
Conversation
Signed-off-by: Thomas Kosiewski <tk@coder.com>
Signed-off-by: Thomas Kosiewski <tk@coder.com>
Signed-off-by: Thomas Kosiewski <tk@coder.com>
…5971) Signed-off-by: Thomas Kosiewski <tk@coder.com>
Signed-off-by: Thomas Kosiewski <tk@coder.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
This was referenced Oct 10, 2026
yermakoffivan
pushed a commit
to yermakoffivan/mux
that referenced
this pull request
Oct 10, 2026
## Summary The desktop cold-start job from coder#5997 uploads a `cold-start.json` that is not valid JSON. This PR moves the stdout redirect inside `sh -c`, so only the runner's JSON reaches the file. Refs coder#5971. No product change. ## Background The first A/A dispatch (run https://github.com/coder/xum/actions/runs/38013815349, base = head = `d0a00215b0`, 20 pairs) succeeded, but its artifact starts with 46 lines that are not JSON: 44 runner progress lines and 2 `Downloading Electron binary...` lines, followed by the JSON document. Ubuntu 22.04's `xvfb-run` runs its command with `"$@" 2>&1` (line 184 of `debian/local/xvfb-run` on `ubuntu/jammy-updates`), so the runner's stderr went into the redirected stdout. Current Debian removed the `2>&1`, which is why this was easy to miss. ## Implementation `xvfb-run -a sh -c 'node ... --json > cold-start.json'`: the inner shell redirects only the runner's own stdout, so stderr (progress lines) now goes to the job log. The variables still reach the step only through `env:` and are validated by the existing regex step. A scoped `# shellcheck disable=SC2016` marks the single quotes as intended. ## Validation - I ran the exact step text under a stand-in `xvfb-run` that does `"$@" 2>&1`, with a stub `node`. The old form gives a file that does not parse. The new form gives a file that `jq -e .` parses whole, and the stub's stderr still shows on the console. - `make lint-actions` (actionlint and zizmor) and `make static-check` pass. - After merge I will dispatch the A/A again and check that the whole uploaded file parses. --- _Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking: `high`_ <!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=high -->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the desktop cold-start A/B runner for the first-load JS plan (T3, Refs #5971) and a
workflow_dispatchjob that runs it on CI. It measures thexum:app-shell-readymark from #5981 in the Electron renderer. Nosrc/change and no user-visible change.Background
The T3 code-splitting PRs must show that they do not slow down Electron startup. The plan's desktop protocol (D2) uses the mark's
startTime, measured on cold launches with base and head interleaved. This dev host has no display server, so the measurement of record runs on a CI runner underxvfb-run.Implementation
scripts/perf/desktopColdStartStats.ts(pure):launchPlanalternates 2 warm-ups per arm, then runs pairs in ABBA order (base-head, head-base, ...) so order effects cancel.pairedRelativeDeltareturns the mean per-pair relative delta(head − base)/base, its sd, and the one-sided 95% half-width and upper bound. It uses a one-sided t table (t = 1.729 at 19 df), not the two-sided table inbenchStats.ts.scripts/perf/desktopColdStart.tslaunches each built tree's own Electron the same way the load-dist e2e harness does (XUM_E2E=1 XUM_E2E_LOAD_DIST=1, mock AI). Before every launch it copies a seeded root fresh to one fixed path, becauseconfig.jsonholds absolute paths. It reads exactly one mark per launch and fails the run on any launch failure, with no retries. It prints a per-launch table and the summary, or--json.node --import tsx), not Bun. Under Bun 1.3.12, Playwright's_electron.launchnever finishes the websocket upgrade to Electron's debugger, so every launch hangs. Remote UAT showed this.bun x playwright testalso runs under Node.console.logto stderr, which keeps--jsonoutput valid..github/workflows/desktop-cold-start.yml: dispatch only (inputsbase_sha,head_sha,pairs). Permissions arecontents: read, checkout usespersist-credentials: false, and the action SHAs are copied fromperf-profiles.yml. Inputs reach shell steps only throughenv:and are checked with a regex. The job builds head at the workspace root and base in agit worktree, runs the runner underxvfb-run -a, and uploadscold-start.json. The runner comes from the head tree, sohead_shamust contain this PR.Validation
--jsonruns both exited 0. Both runs made 10 launches in the orderbw hw bw hw b0 h0 h1 b1 b2 h2(b/h= base/head arm,w= warm-up, digit = pair index). A recompute matchedstats, and no temp dir was left behind.--pairs 1exits 2.--pairs 3 --jsongives 10 launches in ABBA order with stats that match a recompute. Eight--timeout-msruns from 1 to 200 ms each exit 1 in about 1 s, with no temp dir or Electron process left. Bad input exits 2. A run with two trees whose Electron binary must first be downloaded keeps stdout valid JSON.tsxcomes in only transitively (throughe2e), not as a direct dependency. The base tree's Electron can download before a bad head tree is rejected.make lint-actions(actionlint and zizmor) andmake static-checkpass.check-react-compilerstill prints23/24 hot components compile (1 known skipped).Risks
None for the product. The workflow runs only on manual dispatch, with read-only permissions.
Generated with
xum• Model:anthropic:claude-opus-5-5• Thinking:high