Skip to content

Conversation

@captainsafia
Copy link
Member

@captainsafia captainsafia commented Aug 13, 2024

Contributes towards #56829. Refresh of #56599.

  • Replace use of Enumerable.All with a custom implementation of DictionaryEquals and ListEquals to avoid overhead due to lambda capture in existing comparers.
  • Cast to concrete collection types in DictionaryEquals and ListEquals to avoid interface dispatch overhead. See Remove LINQ usage from OpenAPI comparers #56599 (comment) fore more info.

Resulting benchmarks from this change are as follows:

Before

Method EndpointCount Mean Error StdDev Op/s Gen0 Gen1 Allocated
GenerateDocument 10 303.7 μs 2.43 μs 2.27 μs 3,292.87 3.9063 - 538.06 KB
GenerateDocument 100 2,843.4 μs 35.50 μs 29.65 μs 351.69 31.2500 15.6250 4891 KB
GenerateDocument 1000 31,125.8 μs 492.27 μs 460.47 μs 32.13 333.3333 166.6667 48417.5 KB

After

Method EndpointCount Mean Error StdDev Op/s Gen0 Allocated
GenerateDocument 10 270.5 us 1.39 us 1.30 us 3,697.22 2.9297 434.9 KB
GenerateDocument 100 2,484.8 us 25.84 us 24.17 us 402.45 31.2500 3944.06 KB
GenerateDocument 1000 27,413.2 us 219.91 us 194.95 us 36.48 166.6667 39030.74 KB

@captainsafia captainsafia requested a review from a team as a code owner August 13, 2024 20:42
@ghost ghost added the needs-area-label Used by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically label Aug 13, 2024
@captainsafia captainsafia added area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates feature-openapi area-minimal Includes minimal APIs, endpoint filters, parameter binding, request delegate generator etc and removed needs-area-label Used by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically labels Aug 13, 2024
return x.PropertyName == y.PropertyName &&
x.Mapping.Count == y.Mapping.Count &&
x.Mapping.Keys.All(key => y.Mapping.TryGetValue(key, out var yValue) && x.Mapping[key] == yValue);
ComparerHelpers.DictionaryEquals((Dictionary<string, string>)x.Mapping, (Dictionary<string, string>)y.Mapping, StringComparer.Ordinal);
Copy link
Member

Choose a reason for hiding this comment

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

I don't think these should be casted without checking the type. OpenAPI library automatically creates Dictionary and List instances for these properties, but someone could set their own IDictionary implementation.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep, I shared this insight over in the other PR. I was optimizing for code brevity here given how unlikely it is for these to be overridden with non-default implementations but I can adjust if we want things to be a little sturdies here.

Copy link
Member

Choose a reason for hiding this comment

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

I think making ListEquals and DictionaryEquals a little bigger to handle other types is worth the safety. Also, it allows the casts to be removed when calling them.

@captainsafia captainsafia merged commit a360882 into main Aug 14, 2024
@captainsafia captainsafia deleted the safia/oai-perf-2 branch August 14, 2024 15:41
@dotnet-policy-service dotnet-policy-service bot added this to the 9.0-rc1 milestone Aug 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-minimal Includes minimal APIs, endpoint filters, parameter binding, request delegate generator etc area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates feature-openapi

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants