Skip to content

Cache parameter writer lookups #24536

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

Merged
merged 3 commits into from
Aug 3, 2020

Conversation

SteveSandersonMS
Copy link
Member

See description at #24466.

This improves the ComplexTable benchmark by about 7.3% (though the op count improves by 17%).

@SteveSandersonMS SteveSandersonMS added the area-blazor Includes: Blazor, Razor Components label Aug 3, 2020
@SteveSandersonMS SteveSandersonMS requested a review from a team August 3, 2020 14:38
@SteveSandersonMS SteveSandersonMS force-pushed the stevesa/perf-parameter-writers-cache branch from 84390b7 to b1acbbb Compare August 3, 2020 14:40
@SteveSandersonMS SteveSandersonMS self-assigned this Aug 3, 2020
public WritersForType(Type targetType)
{
WritersByName = new Dictionary<string, IPropertySetter>(StringComparer.OrdinalIgnoreCase);
_underlyingWriters = new Dictionary<string, IPropertySetter>(StringComparer.OrdinalIgnoreCase);
_writerCache = new ConcurrentDictionary<StringObjectIdentityKey, IPropertySetter?>();
Copy link
Contributor

@pranavkm pranavkm Aug 3, 2020

Choose a reason for hiding this comment

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

There's a ReferenceEqualityComparer<T> type in 5.0 you could use. You can avoid create the type type. Basically,

Suggested change
_writerCache = new ConcurrentDictionary<StringObjectIdentityKey, IPropertySetter?>();
_writerCache = new ConcurrentDictionary<string, IPropertySetter?>(ReferenceEqualityComparer<string>.Instance);

Copy link
Member Author

Choose a reason for hiding this comment

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

Great, thanks for the tip! I switched over to this and not only does it save code, but it reduces the instruction count by another 1% on the ComplexTable benchmark (probably because it no longer has to call the constructor or field setter for my custom type).

@@ -41,7 +42,7 @@ public static void SetProperties(in ParameterView parameters, object target)
foreach (var parameter in parameters)
{
var parameterName = parameter.Name;
if (!writers.WritersByName.TryGetValue(parameterName, out var writer))
if (!writers.TryGetValue(parameterName, out var writer))
Copy link
Contributor

Choose a reason for hiding this comment

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

One additional optimization we could make is to stash the the WritesForType as an internal property on ComponentBase and avoid the dictionary lookup there.

if (target is ComponentBase component)
{
  component.Writer ?? = new WritersForType(targetType);
  _writer = component.Writer;
}
else
{
 // old code
}

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for the suggestion. Since this didn't show up in the profile traces as a hot path, I'd prefer not to add an optimization for it.

I guess that doing the lookup for this dictionary is relatively cheap because component.GetHashCode() is much cheaper than computing a string hash.

@SteveSandersonMS SteveSandersonMS force-pushed the stevesa/perf-parameter-writers-cache branch from b1acbbb to a08a27d Compare August 3, 2020 17:09
@SteveSandersonMS SteveSandersonMS merged commit 7e11c3c into master Aug 3, 2020
@SteveSandersonMS SteveSandersonMS deleted the stevesa/perf-parameter-writers-cache branch August 3, 2020 20:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-blazor Includes: Blazor, Razor Components
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Blazor WebAssembly perf: Optimize parameter writer dictionary lookup
2 participants