[release/9.0-staging] Fix to #35206 - Query/Perf: don't use Invoke in value comparer lambdas when constructing shaper with PopulateCollection #35207
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #35206
Port of #35128
Description
In EF9 we changed the way we generate shapers in preparation for AOT scenarios. We no longer can embed arbitrary objects into the shaper, instead we need to provide a way to construct that object in code, or simulate the functionality it used to provide. One of the examples was use of ValueComparers in PopulateIncludeCollection. Now instead of passing list of ValueComparer objects to use (which we can't reliably generate in code), we pass the delegate which is used to compare two values:
This incurs a performance hit on some scenarios with collections, but can be improved by simplifying the delegate we use. Instead of having nested lambdas and using Invoke, we can inline the body of the nested lambda directly into the outer lambda, like so:
This one change yields significant improvement in the affected scenarios (reducing both time spent and allocations):
ef 9 before the Invoke fix
ef 9 after the invoke fix
Customer impact
Queries using collection navigation with significant amount of data suffer large performance degradation when compared with EF8
How found
Multiple customer reports on 9.0.0
Regression
Yes, from 8.0. (perf regression only, no functional regression)
Testing
Ad-hoc perf testing with BenchmarkDotNet. Functional change already covered by numerous tests.
Risk
Low. Inlining a nested lambda (rather than invoke) is a common and safe optimization. Quirk added, just in case.