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

Merged
LA
1d ago
+74-1

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 e241a676 (before #35875, the per-window cmux_focus_* handle). Head: #35875's merge c6be9430 (the shared cmux_input_* router).

roundarmsend p50 / p99 (ns)topology p50 / p99 (us)
1base583 / 7098.04 / 9.08
2head625 / 7929.13 / 10.46
3base542 / 7098.04 / 9.08
4head625 / 7929.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 c6be9430 plus this fix (never-merge fix/r-input-focus-bench-fix-nomerge 08cea8157b8, 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 9bce0f592de = feat 2c87a7e5901 + 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 3b4b7f9bd7b (this branch merged with feat 79a480d5fd8), 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.