Skip to content

Remove all ElementUtil allocations and stop boxing in DispatcherOperation #10903

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 54 commits into
base: main
Choose a base branch
from

Conversation

h3xds1nz
Copy link
Member

@h3xds1nz h3xds1nz commented Jun 2, 2025

Fixes #10679, currently blocked by #10680.

Description

This is a bigger PR, however the impact is proportional to the size of it.

  • Removes all allocations in ElementUtil of DispatcherOperationCallback.
  • Removes all various boxing during invocations and on returns in all automation wrappers / ElementProxy.
  • Removes boxing of TResult when the invocation is not on the same thread / Send priority in DispatcherOperation.
    • It didn't box on same thread / Send priority but the rest was using the object Result.
  • Adds some basic invocation tests for Dispatcher/ElementUtil.
  • Adds nullability annotations to all UIA proxy wrappers (and some interfaces) to further support the effort.
  • Adds basic unit tests for ValueProviderWrapper / ToggleProviderWrapper / RangeValueProviderWrapper / ExpandCollapseProviderWrapper / TransformProviderWrapper that test for both wrapper construction and invocations.

To further reduce the code complexity between legacy/async invocations, the different flavours of DispatcherOperation only contain the respective code-paths that are required, e.g. the non-legacy paths no longer contain wrapped invokes that would never be invoked (as _useAsyncSemantics would be true).

Overall, this will now cause inlining on all the regular hot paths in ElementProxy in tier1, further speeding up most of the synchronous/same-thread invocations (which is often the case).

There's one thing to consider:

  • The only way the ElementUtil inner operation won't complete (when the result would have HasCompleted set to false) is when a CancellationToken would be used - which is never, making this essentially a dead code. But I'm keeping it as-is.

Customer Impact

See #10679 for impact of this change. In the demo app (which is a repro from this repo), it reduces the total allocation in half and reduces the time required (big part is due to allocations, some due to inlining etc.) to complete by 30% on average.

The unit tests here will also help verify changes in #10237.

Regression

No.

Testing

Local build, new unit tests, testing with regular apps and UIA invocations.

Risk

Medium, the changes are quite broad yet simple. I've included numerous tests to ensure functionality.

Microsoft Reviewers: Open in CodeFlow

@h3xds1nz h3xds1nz requested a review from a team as a code owner June 2, 2025 08:55
@dotnet-policy-service dotnet-policy-service bot added PR metadata: Label to tag PRs, to facilitate with triage Community Contribution A label for all community Contributions labels Jun 2, 2025
Copy link

codecov bot commented Jun 2, 2025

Codecov Report

Attention: Patch coverage is 0% with 1293 lines in your changes missing coverage. Please review.

Project coverage is 2.99275%. Comparing base (57fe8ac) to head (3935c32).
Report is 14 commits behind head on main.

Additional details and impacted files
@@                 Coverage Diff                 @@
##                main     #10903          +/-   ##
===================================================
- Coverage   13.48885%   2.99275%   -10.49610%     
===================================================
  Files           3317       3338          +21     
  Lines         664749     664807          +58     
  Branches       74643      74729          +86     
===================================================
- Hits           89667      19896       -69771     
- Misses        572488     644726       +72238     
+ Partials        2594        185        -2409     
Flag Coverage Δ
Debug 2.99275% <0.00000%> (-10.49610%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Community Contribution A label for all community Contributions PR metadata: Label to tag PRs, to facilitate with triage
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Invoke in ElementUtil and ElementProxy cause unnecessary delegate allocations
1 participant