Skip to content

MethodBuilder optimizations#760

Merged
kevingosse merged 5 commits into
masterfrom
kevin/methodbuilder
Jun 26, 2020
Merged

MethodBuilder optimizations#760
kevingosse merged 5 commits into
masterfrom
kevin/methodbuilder

Conversation

@kevingosse

Copy link
Copy Markdown
Contributor

Bunch of optimizations for MethodBuilder (used in most integrations as far as I can tell)

  • Add generic overloads to WithParameters and eagerly resolve the type, to avoid boxing when possible
  • Remove all the boxing in the KeyComparer
  • Directly use the types in the key instead of concatenating them into strings
  • Embed the builder in the key (removes the closure allocation from GetOrAdd, and gives a nice speed boost by making the key object much lighter)

The review is quite big so I split it into multiple commits, to make the changes easier to understand.

The remaining heap allocations come from the MethodBuilder itself. I tried changing it into a struct, but the object is so big that it degraded performance quite a bit. Maybe it's possible to avoid that by using the in/ref keywords, but this would require a big refactoring for a small gain so I'd rather take care of other optimizations first.

BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19041.329 (2004/?/20H1)
Intel Core i7-9750H CPU 2.60GHz, 1 CPU, 12 logical and 6 physical cores
  [Host]     : .NET Framework 4.8 (4.8.4180.0), X64 RyuJIT
  DefaultJob : .NET Framework 4.8 (4.8.4180.0), X64 RyuJIT

Method Mean Error StdDev Ratio Gen 0 Gen 1 Gen 2 Allocated
MethodBuilder_Old 1,027.4 ns 11.68 ns 9.75 ns 1.00 0.2003 - - 1268 B
MethodBuilder_New 158.5 ns 1.51 ns 1.41 ns 0.15 0.0279 - - 177 B

@kevingosse
kevingosse requested a review from a team as a code owner June 19, 2020 14:16
@kevingosse kevingosse added the type:performance Performance, speed, latency, resource usage (CPU, memory) label Jun 19, 2020
@zacharycmontoya

Copy link
Copy Markdown
Contributor

This looks good! Do you need to update the integrations to consume the WithParameters changes or are the integrations going to keep their existing codepaths?

- Use a cached empty array
- Add generic overloads and eagerly fetch type to reduce boxing
This removes the closure allocation around GetOrAdd and makes the key much nimbler, which results in a nice speed boost
@kevingosse
kevingosse force-pushed the kevin/methodbuilder branch from 02adfd7 to 672de6f Compare June 24, 2020 16:31
@kevingosse

Copy link
Copy Markdown
Contributor Author

This looks good! Do you need to update the integrations to consume the WithParameters changes or are the integrations going to keep their existing codepaths?

Generic overloads have a higher priority, so the integrations should automatically use them

@zacharycmontoya zacharycmontoya left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good and I'm looking forward to seeing the new performance numbers! Great work

@lucaspimentel lucaspimentel changed the title Kevin/methodbuilder MethodBuilder optimizations Jun 24, 2020

@lucaspimentel lucaspimentel left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice!

@kevingosse
kevingosse merged commit 388fa1c into master Jun 26, 2020
@kevingosse
kevingosse deleted the kevin/methodbuilder branch June 26, 2020 14:34
@zacharycmontoya zacharycmontoya added this to the 1.18.2 milestone Jul 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:performance Performance, speed, latency, resource usage (CPU, memory)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants