Skip to content
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

Remove allocations in BaseUriHelper, improve resource resolution performance #10328

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

h3xds1nz
Copy link
Member

@h3xds1nz h3xds1nz commented Jan 23, 2025

Currently blocked by #9822, hence draft.

Description

Optimizes methods in BaseUriHelper, removes most of the allocations directly in this class and opens up more optimization possibilities; directly builds upon #9739 and #9822.

  • Removes IsSameKeyToken from SecurityHelper in favour of ReflectionUtils.IsSamePublicKeyToken.
  • BaseUriHelper.GetAssemblyNameAndPart is now fully allocation free.
    • This allows for more optimizations in the future and already makes some paths without any allocations.
    • Instead of returning 3 strings, we return slices in AssemblyPackageInfo ref struct.
  • In FontResourceCache, we can now use AlternateLookup to benefit from this change as well.
  • BaseUriHelper.BaseUri was never set outside static constructor, where it was initialized to the s_packAppBaseUri value,
    hence I've removed the property altogether, which also led to removal of BindUriHelper.BaseUri which was just proxy.
  • Code under CF_Envelope_Activation_Enabled macro was removed, most of the code is already missing in .NET Core than what was in reference files for .NET 3.5 and it is never compiled on NetFX nor on .NET Core.
  • Changes in GetLoadedAssembly bring a bit of an improvement but there's more benchmarking needed on how to handle this chain most efficiently, so keeping as it is right now.

Cherry-picking some cases:

GetAssemblyNameAndPart

Method someUri Mean [ns] Error [ns] StdDev [ns] Gen0 Allocated [B]
Original /Mic(...)xaml [103] 104.95 ns 2.274 ns 6.706 ns 0.0448 752 B
PR__EDIT /Mic(...)xaml [103] 45.42 ns 0.475 ns 0.445 ns - -

AssemblyMatchesKeyString vs ComparePublicKeyTokens

Method someAssembly Mean [ns] Error [ns] StdDev [ns] Gen0 Allocated [B]
Original Syste(...)7798e [89] 40.755 ns 0.3990 ns 0.3537 ns 0.0019 32 B
PR__EDIT Syste(...)7798e [89] 8.135 ns 0.0835 ns 0.0740 ns - -

Customer Impact

Improved performance, decrased allocations.

Regression

No.

Testing

Local build, some assert testing; I'll provide tests before this goes out of draft.

Risk

Low to medium, there are quite a few changes but most of them are rather straightforward.

Microsoft Reviewers: Open in CodeFlow

@h3xds1nz h3xds1nz requested review from a team as code owners January 23, 2025 16:03
@h3xds1nz h3xds1nz marked this pull request as draft January 23, 2025 16:04
@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 draft labels Jan 23, 2025
typeof(BaseUriHelper),
new PropertyMetadata((object)null));

public static readonly DependencyProperty BaseUriProperty = DependencyProperty.RegisterAttached("BaseUri", typeof(Uri), typeof(BaseUriHelper), new PropertyMetadata(null));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the cast to object means that this code will use this constructor.

I'm not sure if it changes the behavior but might as well keep the same behavior and you can juste use a named parameter (Which IMO is also cleaner than just having null):

Suggested change
public static readonly DependencyProperty BaseUriProperty = DependencyProperty.RegisterAttached("BaseUri", typeof(Uri), typeof(BaseUriHelper), new PropertyMetadata(null));
public static readonly DependencyProperty BaseUriProperty = DependencyProperty.RegisterAttached("BaseUri", typeof(Uri), typeof(BaseUriHelper), new PropertyMetadata(defaultValue: null));

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, what's wrong with the original indentation ? Most dependency/attached property registration in this repo use the same indentation style, I don't see why we should change it. Personally I prefer the previous style and other repos like WinForms have a recommended max line length (WinForms uses recommended < 120 and max < 150)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It won't change behaviour but I like the named argument there, let's use that. Thanks.

As for indentation; since the class is 90% changes, it was auto format. Reverted it as the line is indeed too long but I wouldn't go as far as saying "use the same indentation style", I can select a random file e.g. DataGrid files and I'll see 6 different ways to indent a dependency property. 😀

@h3xds1nz h3xds1nz force-pushed the baseurihelper-optimizations branch from 8c6e0ca to dae54ba Compare February 3, 2025 11:34
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 draft PR metadata: Label to tag PRs, to facilitate with triage
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants