Skip to content

Avoid repeated selector walks and live UIA pattern probes - #450

Merged
crowecawcaw merged 2 commits into
mainfrom
fix/group-selector-uia-query-performance
Sep 29, 2026
Merged

crowecawcaw merged 2 commits into
mainfrom
fix/group-selector-uia-query-performance

Conversation

@crowecawcaw

Copy link
Copy Markdown
Contributor

Summary

  • Cache each parent's children once for the duration of a grouped selector query. The existing path-based clause matcher still determines document order, :nth, and deduplication; later clauses reuse the same query-local snapshots instead of repeating provider calls. A unit test counts provider fetches across five clauses, including a child combinator and :nth.
  • Include the six common UIA patterns in the existing bulk cache request and read their interfaces from the cache. This removes six live pattern-acquisition probes per element. Window and transform patterns remain role-gated and live. Public APIs are unchanged.

Motivation and measurements

sfmtool #647 reports that a GitHub-hosted Windows UIA tree walk took about 18.6 seconds; avoiding most accessibility walks cut its UI test from hundreds of seconds. sfmtool #653 reports a direct UIA walk of 52 nodes taking about 35 ms locally, supporting a large host/runner effect. This PR removes two xa11y costs that we can isolate locally, while the hosted-runner gap still needs an A/B run on that runner.

On this Windows machine, with the same 69-node AccessKit fixture and four warm runs:

Query Main before Child cache Child + UIA pattern cache
App root, one clause 58–65 ms 58–63 ms 49–62 ms
App root, five clauses 282–318 ms 58–65 ms 57–61 ms
Window root, one clause 43–48 ms 41–45 ms 29–35 ms
Window root, five clauses 41–46 ms 42–46 ms 30–36 ms

The final tree output was identical across all 76 CLI lines before and after pattern caching, including actions and states. A separate direct UIA probe on 69 nodes found six live pattern acquisitions cost 40–62 ms, versus 9–11 ms when those patterns were prefetched; the number of supported patterns stayed at 37.

Validation

  • cargo clippy --workspace --all-targets -- -D warnings — passed.
  • cargo test -p xa11y-windows — 81 passed.
  • Core selector tests — 96 passed, including the new fetch-count test.
  • scripts/run_integ_tests_windows.ps1 selector_group_ — 6 passed.
  • Full Windows integration — 152 passed, 9 failed twice. All nine require foreground focus or simulated input in this desktop session: SetForegroundWindow was denied by the foreground lock, SendInput returned error 5, and no process was reported foreground. Action, selector, value, and state tests passed.
  • cargo xtask test-integ reports that the command is unsupported on Windows; the Windows integration script above is the repository's runnable equivalent.
  • cargo xtask check passed the Rust, JS, formatting, and parity checks, but could not finish its Python checks because this host Python lacks pip and pytest.

The deterministic provider-fetch assertion guards against another clause-count multiplier without a timing threshold that would be flaky on shared CI runners. The hosted Windows slowdown itself remains unreplicated locally and should be measured in CI before claiming an end-to-end fix for that environment.

@crowecawcaw
crowecawcaw marked this pull request as ready for review September 29, 2026 05:17
@crowecawcaw
crowecawcaw merged commit bcc4fac into main Sep 29, 2026
73 of 74 checks passed
@crowecawcaw
crowecawcaw deleted the fix/group-selector-uia-query-performance branch September 29, 2026 05:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant