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

Cache FakeOptions constructor to improve performance #1466

Closed
blairconrad opened this issue Oct 3, 2018 · 9 comments
Closed

Cache FakeOptions constructor to improve performance #1466

blairconrad opened this issue Oct 3, 2018 · 9 comments

Comments

@blairconrad
Copy link
Member

blairconrad commented Oct 3, 2018

For a lark, I profiled creating 100,000 instances of a small interface (after warming up FakeItEasy by faking a different interface). Using dotTrace, I found that DefaultFakeAndDummyManager.BuildProxyOptions was a hotspot. So I started caching the constructor by type of Fake and found this difference:

image

BuildProxyOptions drops from 19.10% of the total time to 9.95%. Or if you prefer the diff view:

image

Of course we're trading away some storage space. If we end up faking many different types once, this is a bad tradeoff, but if types are faked more than once, it may be a benefit.

Also, in many cases we don't even need a FakeOptions object. I can explore dropping the construction step as well.

@blairconrad
Copy link
Member Author

Actually, I may have come up with a nice way to not construct the FakeOptions object. Will explore later.

@thomaslevesque
Copy link
Member

Well done, @blairconrad! Looks like a good improvement.

@thomaslevesque
Copy link
Member

Actually, I may have come up with a nice way to not construct the FakeOptions object. Will explore later.

Yes, it would be even better, I guess.

@blairconrad
Copy link
Member Author

Rerunning with FakeOptions creator cached as a delegate (and in release mode this time; other numbers were in debug):

image

27.04% to 2.93%. Not bad. Thanks for the push, @thomaslevesque. I'll work on avoiding construction next.

@blairconrad
Copy link
Member Author

I was originally thinking we could avoid creating the object when users don't use creation method that specifies an option builder action, but we also have to make sure there's no IFakeOptionsBuilder, and that's more involved. It might still eventually be worthwhile, but if the new 2.93% number is to be believed, maybe it's not our next stop.

@blairconrad blairconrad added this to the vNext milestone Oct 4, 2018
@blairconrad
Copy link
Member Author

Using BenchmarkMockNet to test constructors. With FakeItEasy 4.8.1

Method Mean Error StdDev Scaled ScaledSD
Stub 8.375 ns 6.764 ns 1.757 ns 1.00 0.00
FakeItEasy 11,059.153 ns 2,079.941 ns 540.257 ns 1,364.10 243.18
Moq 5,059.672 ns 1,041.998 ns 270.655 ns 624.09 111.94
NSubstitute 8,111.013 ns 5,264.036 ns 1,367.314 ns 1,000.46 230.82
Rocks 4,221.011 ns 4,767.949 ns 1,238.457 ns 520.65 165.25

Using BenchmarkMockNet to test constructors. With a build including this issue:

Method Mean Error StdDev Scaled ScaledSD
Stub 7.039 ns 2.711 ns 0.7042 ns 1.00 0.00
FakeItEasy 8,046.398 ns 470.824 ns 122.2949 ns 1,151.62 96.61
Moq 6,175.403 ns 4,300.547 ns 1,117.0510 ns 883.84 161.06
NSubstitute 5,959.644 ns 129.430 ns 33.6191 ns 852.96 70.74
Rocks 3,990.786 ns 3,982.395 ns 1,034.4122 ns 571.17 141.03

Take with grain of salt. The computer was doing other things. But still, I'm pleased with the change.

@thomaslevesque
Copy link
Member

It certainly looks much better! I think I'll do some profiling tonight, to see if there's more to be gained.

@blairconrad
Copy link
Member Author

I'm sure there's some fat to trim.

@thomaslevesque
Copy link
Member

This change has been released in FakeItEasy 5.0.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants