-
-
Notifications
You must be signed in to change notification settings - Fork 803
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
Mock verification slow with It.Is(Expression) #1420
Comments
There was another issue a few years ago about caching expression trees to improve performance; IIRC, that was one of the reasons that led to the IIRC, the reason why the cache wasn't added directly to the default implementation was that there was some uncertainty about how to unambiguously recognize already compiled expression trees and map them to a cached delegate (i.e. how to prevent false positives in the cache lookup). I suppose if the caching logic is reliable and not overly complex, then that previous decision could be revisited. What does your caching implementation look like? |
@peterder72, I see. My apologies for the misunderstanding. Looks like a reasonable change to make. 👍 The only thing I'm left wondering is whether compiling the expression tree once, ahead-of-time instead of once per invocation of the matcher could possibly affect how & when captured variables get evaluated. I don't think so, but it may be worth verifying. |
@stakx I was also thinking about the same thing, but I can't see anything that can become an issue here, since nothing is captured in the scope of It.Is, all references come from the caller. If you can think of how it could go wrong so that I can put it under test, let me know, I'll also give it a think for now |
@peterder72, I was mostly thinking about things like: var obj = ...;
... It.Is(x => x == obj) ...
// ^^^
// when / how often does this captured variable get evaluated? But on second thought, even that shouldn't be a problem, since compilation in all probability does not perform any kind of partial evaluation. I can't think of any other reasons why the change shouldn't be made. Looks good to me. (Be advised that I am not committing anything to this repo for the time being, due to the recent SponsorLink disaster, so I likely won't be the one merging your PR if you decide to submit one.) |
Due to lack of recent activity, this issue has been labeled as 'stale'. |
If you submit a PR for this, I'd gladly merge it. |
Ah, completely forgot about this one, submitted #1512. It's that same fork I used back when I created this issue, but no conflicts it seems |
Mock verification is very slow when used with expressions and large amount of invocations. Repro:
On inspection, most of the time is spent compiling the exact same provided match expression, when predicate is executed for each invocation during verification:
This results in huge performance drop on large number of invocations and unnecessary allocations, while not serving any purpose. From what I can see, this issue has not been discovered previously. I was able to trace it back to this commit, but it might've been still present in a different form.
The solution here would be to only execute the compilation once, and then pass the compled delegate into the match factory method:
I have implemented a fix on my fork, benchmark results for pre, post, and IsAny (for comparison) is as follows:
Benchmark code:
Since I already have a fix on my fork, I'll be happy to submit a PR for this issue myself
The text was updated successfully, but these errors were encountered: