-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Optimize ResourceContainer/AssemblyLoadEventHandler methods, remove allocs #9822
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good! Does the benchmark handle the startup of an app with something bound to an embedded image resource? There's a call to Assembly.Load in the call stack of ResourceContainer.GetPart (GetPart -> GetPartCore -> GetResourceManagerWrapper -> BaseUriHelper.GetLoadedAssembly -> Assembly.Load) and it feels like this is going to be the largest performance killer in the worst-case scenario; I'm curious to see whether it's triggered under normal circumstances.
src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/AppModel/ResourceContainer.cs
Show resolved
Hide resolved
src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/AppModel/ResourceContainer.cs
Outdated
Show resolved
Hide resolved
@adamsitnik wanted to point this out to you as it is doing some assembly name parsing in a hot path for WPF. |
e553fa0
to
0d1084d
Compare
Thank you @h3xds1nz for your continuous contributions 😄 |
@himgoyalmicro Thank you, happy this one is in <3 |
Description
Optimizes two rather important startup methods in
ResourceContainer
class, the handler for runtime assembly load events -OnAssemblyLoadEventHandler
andGetResourceManagerWrapper
. This saves several milliseconds upon startup.StringComparer.OrdinalIgnoreCase
as it would be slower by ~60ns in the final solution.RuntimeAssembly
), I've re-used the Optimize retrieval of simple name from Assembly.FullName, fix up faulty methods #9739 and added a new method forVersion
/PublicKeyToken
ArrayPool<char>
for the unlikely event of needing an array (256+ chars) but seems redundant to initialize it this early, and we shall not really need to allocate an array anyways in 99% cases.AlternativeLookup
, this now becomes fully allocation-free given that usually only 1 entry is in the dictionary.ToLowerInvariant
produces same-length output, the own function's sanity check and several other dotnet runtime libraries (plus tons of user code) depend on this behavior of per-character folding.Do note that these benchmarks measure throughput and allocations (accurate), the savings are in milliseconds this early.
Allocations are dependent on presence of public key / assembly name length, this just illustrates general scenario.
Single throughput of AssemblyLoadHandler
Standard app startup (28 libraries loaded)
Customer Impact
Improved startup performance, decreased startup allocations.
Regression
No.
Testing
Local build, running few sample apps using resources and verifying functionality.
Risk
Low, I believe I didn't achieve any change of the behavior, even unintentionally.
Microsoft Reviewers: Open in CodeFlow