Skip to content

perf(input-router): a topology report that only selects other tabs keeps the router's tab index (R-INPUT S2 focus A/B) - #36262

Merged
lawrencecchen merged 4 commits into
feat-cmux-nextfrom
fix/r-input-tab-index-keep
Nov 5, 2026
Merged

lawrencecchen merged 4 commits into
feat-cmux-nextfrom
fix/r-input-tab-index-keep

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

REWRITE R-INPUT S2 acceptance, the focus bench (DESIGN.md: "focus bench within 5 %"). After S2b step B (#35875) every window's focus goes through the input router, and the router rebuilt its tab index on every topology report that ran the reducer, also when the report only selected another tab of the same panes (Cmd-1, a tab click, a switch back). The index holds each tab's id, surface, kind and host terminal, never the selection, so that rebuild made the same index again: one Arc<str> per tab id, per surface and per host terminal, and two map inserts per tab.

What changes:

  • InputRouter::focus_event keeps the index when the report lists the same tabs in the same order as the state it replaces (lists_same_tabs, a comparison of the two tab lists: Tab is id, surface, kind and terminal). A report that adds, drops, moves or changes a tab rebuilds it as before. An equal report still runs no reducer and no rebuild.
  • No change to the C ABI, to any reply or to the app.

Measured (the S2 focus A/B that found it)

Never-merge FocusMachineSendBench (branch fix/r-input-focus-bench-nomerge): one FocusMachine.send (a focus event's reduction and its reply read) and one topology report of a 30-pane window (two tabs a pane), Release configuration, exclusive measurement steps on one perf mini (cmux23-perf), alternating arms. Base: feat e241a67 (before #35875, the per-window cmux_focus_* handle). Head: #35875's merge c6be943 (the shared cmux_input_* router).

round arm send p50 / p99 (ns) topology p50 / p99 (us)
1 base 583 / 709 8.04 / 9.08
2 head 625 / 792 9.13 / 10.46
3 base 542 / 709 8.04 / 9.08
4 head 625 / 792 9.13 / 10.33

Both head rounds agree, and so do both base rounds: the topology report through the router was 13 % slower at p50 than the window handle alone (8.04 -> 9.13 us; p99 9.08 -> 10.33-10.46 us), and a focus event 7-15 % slower (542-583 -> 625 ns). The acceptance is 5 %. In each round the bench's report changes which tab every pane shows, the case this PR fixes. The app links the Rust code from the pinned CCmuxAppFFI release (Package.swift), so a Swift bench at a branch commit runs the pinned FFI, not this change: a run at c6be943 plus this fix (never-merge fix/r-input-focus-bench-fix-nomerge 08cea81, step ce9d1f26, cmux23-perf) measured the unfixed router (send p50 625 ns, topology p50 9.13 us, the head's numbers), and I stopped that A/B. The end-to-end A/B runs after this merges, when app-ffi-release.yml publishes cmux-app-ffi-<merge sha> and the next FFI pin lands; S2's 5 % acceptance stays open until then. The cause this PR removes is measured directly by the allocation test below.

Tests

key_router::allocations::a_report_that_only_selects_another_tab_rebuilds_no_tab_index (cmux-tui/crates/cmux-focus-core/tests/input_router), red first: a 6-pane window whose panes each show their other tab; the router must make no more allocations for that report than WindowFocus alone. Red on feat without the fix (never-merge fix/r-input-tab-index-red-nomerge 9bce0f5 = feat 2c87a7e + the test), step a2ca7440d0ae3209c49c0ff3 (Linux): "the router made 42 allocations for a report that only selects other tabs, the window focus alone 12": 30 more, one Arc<str> for each of the 12 tab ids, 12 surfaces and 6 host terminals. Green: the full Rust check at 3b4b7f9 (this branch merged with feat 79a480d), step b78d2d95 (Linux): 1149 of 1149 tests passed, this one among them.

(The test first went into the FFI crate's tests/input_handle.rs, next to step A's corpus test. That crate is its own Cargo workspace, which the fleet's cmux-tui-rust-check.sh does not build, so the red step ran 0 tests; the test moved to cmux-focus-core, which the check runs.)

Observed / Not run

  • Observed: the bench rounds above; the red step; the green full Rust check (1149 of 1149); the prepush gate (no new violations).
  • Not run: the Swift A/B of this fix (it needs the published FFI and its pin, after merge); the FFI crate's own cargo test (CI's cmux-layout-reducer-ffi (own workspace) step runs it; step A's corpus test there compares every reply of the input handle with the window handle's).

Changelog

none

No capture: no visible change (a router cost).


Autofix with [code]smith
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Stops the input router from rebuilding its tab index on topology reports that only change the selection, so Cmd-1, tab clicks, and switch-backs no longer pay the rebuild cost. A report that lists the same tabs in the same order keeps the index; one that adds, drops, moves, or changes a tab still rebuilds it. Measured in the S2 focus A/B, the rebuild made a 30-pane topology report 13% slower through the router (8.04 -> 9.13 us p50) and focus events 7-15% slower, over the 5% acceptance.

No change to the C ABI, to any reply, or to the app.

Tests

  • Adds an allocation test asserting the router makes no more allocations than WindowFocus alone for a selection-only report.

Written for commit 3b4b7f9. Summary will update on new commits.

View guided diff Turn on auto-fix

…ds no allocation in the router (red, R-INPUT S2 focus A/B)
…the router's tab index (a selection change rebuilt it: +13 % per report in the S2 focus A/B)
…us-core against the window focus alone (the FFI crate is its own workspace, which the fleet's Rust check does not build)
@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review 3b4b7f9: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr36262 -f ref=fix/r-input-tab-index-keep -f platform=macos -f backend_mode=local

red: cmux-next checks (god files, concurrency, crash safety, l10n); no finished base run on 64d6b1b to compare; do not merge until green; see lane-rules

Shipped in:

The feat-cmux-next push run https://github.com/manaflow-ai/cmux/actions/runs/41990669105 at cf6dec5 failed: cmux-next checks (god files, concurrency, crash safety, l10n).
Those jobs last passed at e025b48. This pull request is one of 5 merged since: #36262, #36236, #36057, #36285, #36207.
If the failure is in your change, fix forward on feat-cmux-next. Pull requests run only the tiers their paths reach (docs/ci/cmux-next-tiers.md); label a batch PR full-ci to run them all before merging.

@lawrencecchen cmux-next checks (god files, concurrency, crash safety, l10n) first failed at merged commit 7a3ac7fedc0796650aba8a733621da0addbcd3ee after green e025b48b6ef84ee9246e71a750d9ca4105dd0dbf.
Bisected completed CI verdicts for every first-parent commit up to 3deee62e975edd395a27a9d1b414d98c881e1ca0 (https://github.com/manaflow-ai/cmux/actions/runs/41990504179); 1 midpoint lookups. The verified history is monotonic.
Skipped, missing, conflicting, infrastructure, or non-monotonic evidence stays unresolved.

@lawrencecchen lawrencecchen added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Nov 5, 2026
@blacksmith-sh

blacksmith-sh Bot commented Nov 5, 2026

Copy link
Copy Markdown

Found 6 test failures on Blacksmith runners:

Failures

Test View Logs
/tmp/tmpf3ga6wlq/summary-missing.json (live):/summary-missing.json (live): View Logs
/tmp/tmptbgfswum/summary-fail.json (live):/summary-fail.json (live): View Logs
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows/
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows
View Logs
[new_workspaces] the window draws no frames/[new_workspaces] the window draws no frames View Logs
[tabs] debug.tab_switch timed 0 of 40 switches/
[tabs] debug.tab_switch timed 0 of 40 switches
View Logs
[tabs] the window draws no frames/[tabs] the window draws no frames View Logs

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@lawrencecchen

Copy link
Copy Markdown
Contributor Author

Review (independent review subagent): SHIP at 3b4b7f9

Read-only correctness review of the branch's change (7e60135, 38789f7, cb89e40) at the merged head:

  • The index reindex builds reads only the flattened tab list (id, surface, kind, terminal: exactly the fields Tab: PartialEq compares), never a pane id, the selection, the workspace or a position, so a report that lists the same tabs builds the same index and no entry can go stale.
  • keeps_index compares the state before the reduction with the incoming report; a non-topology event never ran the reindex block on the base either, and no other event variant changes the tab list.
  • The allocation test fails without the fix (30 extra Arc<str>: 12 tab ids, 12 surfaces, 6 terminals) and passes with it; the counter counts per thread.
  • No reply and no C ABI behavior changes.
  • The reviewer asked for a fleet red of the moved cmux-focus-core test: that is step a2ca7440 at never-merge 9bce0f5 (feat 2c87a7e plus only tests/input_router/key_router/allocations.rs), which failed with 42 against 12 allocations, as the body says.

@lawrencecchen

Copy link
Copy Markdown
Contributor Author

Non-green checks at 3b4b7f9, classified:

@lawrencecchen lawrencecchen added the ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds label Nov 5, 2026
@lawrencecchen
lawrencecchen merged commit 7a3ac7f into feat-cmux-next Nov 5, 2026
231 of 251 checks passed
@lawrencecchen
lawrencecchen deleted the fix/r-input-tab-index-keep branch November 5, 2026 07:53
cmux-bot Bot pushed a commit that referenced this pull request Nov 5, 2026
…edes the older build (#36346)

* ci(app-ffi-release): treeless build checkout; a newer FFI push supersedes the older build

The build job's full clone of every ref was 5 to 10 minutes of a 7 to 15
minute build (12 recent runs); the Rust compile and tests were 1 to 4.
fetch-depth 0 with filter tree:0 keeps every commit and ref the
workflow-delta step reads and fetches trees on demand.

The run-level group (cancel-in-progress: false) made a newer FFI push wait
for the whole older run before building, while the older pin could no longer
land (#36262). The build job now has its own group with cancel-in-progress;
publish is never cancelled, and re-pins stay one at a time in app-ffi-repin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-8707001042ea634e8771

* ci(app-ffi-release): publish one run per commit at a time

Without the run-level group, two runs of one commit (a push and a dispatch,
or two dispatches) could both pass the release view and race the create; the
loser failed with a valid release in place. Publish now has a per-commit
group that never cancels, so the second run finds the release and checks its
checksum.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-8707001042ea634e8771

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

This branch was previously deployed

1 inactive deployment
ci-routing-agent — 3b4b7f9b Deployed Nov 5, 2026 by lawrencecchen via cmux-tui tree preflight #114561
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant