Repository navigation
perf(cmux CLI): workspace list reads the app window without the app's read barrier (CLI-1) - #32201
Conversation
… read barrier (CLI-1 fix 3 red)
… read barrier (CLI-1) Under the TYPING UNDER LOAD L6 load a CLI `workspace list` took up to 4.2 s (32 workers: p50 903 ms, a cluster at 4.08-4.36 s). After the daemon answered, the CLI asked the app which workspace its window shows (`snapshot.get`, the `focused` overlay) with the default read barrier `after: "sync"`: a daemon round trip on the app's connection, then a wait for the app's main actor to publish a snapshot past it, within the app's 2 s deadline. Under load the deadline passed and the CLI asked once more. Which workspace a window shows is the app's own state; no daemon write of the caller changes it (focus goes through the app's focus actions, which answer after the window moved). The overlay now reads the last published snapshot (`after: 0`), answered off the main actor.
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
Shipped in:
|
|
Review (subagent, correctness first): SHIP at 8185ff0 Scope: What the app does with
|
|
Review (subagent, correctness first): SHIP at 82312c5 Scope: the whole diff The fix answers the earlier Medium
Reply shapes (from
|
…dow again with the barrier (#32201 follow-up) (#32327) * test(cmux CLI): a list without the window's workspace reads the window again with the barrier (#32201 review red) * fix(cmux CLI): a list that lacks the window's workspace reads the window again with the barrier (#32201 review) The review of #32201 found one daemon write that can leave the app's last published snapshot behind: `workspace close <shown>` and then `workspace list`. The fast snapshot still shows the closed workspace, so the overlay set every row unfocused. When a list of the app's session lacks the window's workspace, the overlay now reads the window once more with `after: "sync"`; every other list keeps the fast read. The read barrier's doc names the caller-chosen `after`.
Summary
Under the TYPING UNDER LOAD L6 load (STATUS 6075, cmux20), a CLI
workspace listtook up to 4,173 ms (8 workers); with 32 workers (video-extra-2's base self-check) p50 903 ms and a tight cluster at 4.08-4.36 s.Cause: after the daemon answers
workspace list(orshow,rename,move), the CLI asks the app which workspace its window shows (snapshot.get, thefocusedoverlay,cli/app_focus.rs). Every CLI app request carries the read barrierafter: "sync"by default (cli/app.rswith_read_barrier). The app answers it only after aMainActor.runhop, anidentifyround trip on its one daemon connection, and a wait for the main actor to publish a snapshot past that sequence, within its 2 s deadline (ControlRouter+Barrier.swift,AppControl+Barrier.swift). Under load the deadline passes, and the CLI asks once more (is_retryable_read): 2 s + 2 s = the 4.1 s cluster. A list waited for the app's main thread, against the rule "a list call is a read, it must never wait behind the main thread".Fix: the overlay first reads the app's last published snapshot (
after: 0), which needs no daemon round trip (the storm's plainsnapshot.gettook 2.5 ms p50 under the same load). The app may still refresh a stale snapshot on its main actor before it answers (fresh()), as before. Focus goes through the app's focus actions, which answer after the window moved, so a focus is in that snapshot. One daemon write can leave the snapshot behind: closing the workspace the window shows. When a workspace list of the app's session lacks the window's workspace, the overlay reads the window once more withafter: "sync".Not changed: every other CLI app request keeps
after: "sync".Owners: the cmux CLI (cmux-tui/crates/cmux-tui, no OWNERS row) and the app control router (PL-socket / app control, not changed here).
Changelog
cmux workspace listno longer waits seconds for a busy app window under load.Testing
Regression test:
workspace_list_reads_the_window_without_waiting_for_the_apps_read_barrier(cmux-tui,cli/app_focus/tests.rs). A fake app answers a request withafter: "sync"with its own deadline error (a busy main actor) and any other request with the window snapshot. The list must read the window in one request and setfocusedfrom it.snapshot.getcalls, bothafter: "sync"(the first timed out, the retry timed out), sofocusedstayed the daemon's.usage_stats::the_session_list_and_info_carry_what_the_chats_transcript_says(base red on every head today), cmux-tuievery_safe_transport_operation_has_a_noun_first_path(workspace_group.create has catalog fields with no exercised CLI representation: a base red of feat 706ef7f, the catalog op came from another PR), and acpmuxsubsessions_safety(passed when rerun alone: a load flake).Command:
cmux-ci run --class isolated --script scripts/ci/cmux-tui-rust-check.sh --ref SHA --os linux --arg test --arg workspace_list_reads_the_window_withoutReview fix (first review SHIP at 8185ff0 with a Medium: after
workspace close <shown>; workspace list, the fast snapshot can still show the closed workspace): when a list of the app's session lacks the window's workspace, the overlay reads the window once more withafter: "sync". Testa_list_without_the_window_s_workspace_reads_the_window_again_with_the_barrier.after: 0read was sent).Observed / Not run
Observed: the raw L6 calls (8 and 32 workers), the code path, the red and green steps above.
Not run: an L6 round in the real app with this CLI. The A/B needs the app under load; the measurement owner (video-extra-2) has the daemon-stats capture ready for the next L6 rounds.
Need help on this PR? Tag
@codesmith-botwith what you need.Summary by cubic
Fixes
cmux workspace listwaiting seconds for a busy app window under load. The list asked the app which workspace its window shows (snapshot.get) with the default read barrierafter: "sync", which waits for the app's main thread; under load each attempt hit the app's 2 s deadline and the CLI asked twice, so a list took up to 4.2 s.The overlay now reads the app's last published snapshot (
after: 0), answered off the main actor. Which workspace a window shows is the app's own state, and no daemon write of the caller changes it. Other CLI app requests keepafter: "sync".Testing
focusedfrom it.Written for commit 8185ff0. Summary will update on new commits.