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

[release/9.0-staging] Fix to #35208 - Query/Perf: don't compile liftable constant resolvers in interpretation mode #35211

Merged
merged 1 commit into from
Nov 27, 2024

Conversation

maumar
Copy link
Contributor

@maumar maumar commented Nov 26, 2024

Fixes #35208
Port of #35209

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 (using LiftableConstant mechanism), or simulate the functionality it used to provide. At the end of our processing, we find all liftable constants and for the non-AOT case we compile their resolver lambdas and invoke the result with liftable context object to produce the resulting constant object we initially wanted. (in AOT case we generate code from the resolver lambda). Problem is that we are compiling the resolver lambda in the interpretation mode - if the final product is itself a delegate, that delegate will itself be in the interpreter mode and therefore less efficient when invoked multiple times when the query runs. Fix is to use regular compilation rather than interpretation.

Customer impact
Queries using collection navigation with significant amount of data suffer large performance degradation when compared with EF8. No good workaround.

How found
Multiple customer reports on 9.0.0

Regression
Yes, from 8.0.

Testing
Ad-hoc perf testing with BenchmarkDotNet. Functional change already covered by numerous tests.

Risk
Low, quirk added.

Benchmarks

before this change

Method Async Mean Error StdDev Op/s Gen0 Gen1 Allocated
MultiInclue False 487.1 ms 0.99 ms 0.88 ms 2.053 17000.0000 11000.0000 103.29 MB
MultiInclue True 487.4 ms 3.63 ms 3.22 ms 2.052 17000.0000 11000.0000 103.29 MB

after this change

Method Async Mean Error StdDev Op/s Gen0 Gen1 Allocated
MultiInclue False 455.1 ms 8.94 ms 10.29 ms 2.197 11000.0000 6000.0000 67.92 MB
MultiInclue True 435.4 ms 1.77 ms 1.66 ms 2.297 11000.0000 6000.0000 67.92 MB

Port of #35209

**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 (using LiftableConstant mechanism), or simulate the functionality it used to provide.
At the end of our processing, we find all liftable constants and for the non-AOT case we compile their resolver lambdas and invoke the result with liftable context object to produce the resulting constant object we initially wanted. (in AOT case we generate code from the resolver lambda).
Problem is that we are compiling the resolver lambda in the interpretation mode - if the final product is itself a delegate, that delegate will itself be in the interpreter mode and therefore less efficient when invoked multiple times when the query runs.
Fix is to use regular compilation rather than interpretation.

**Customer impact**
Queries using collection navigation with significant amount of data suffer large performance degradation when compared with EF8. No good workaround.

**How found**
Multiple customer reports on 9.0.0

**Regression**
Yes, from 8.0.

**Testing**
Ad-hoc perf testing with BenchmarkDotNet. Functional change already covered by numerous tests.

**Risk**
Low, quirk added.
@maumar maumar changed the title Fix to #35208 - Query/Perf: don't compile liftable constant resolvers in interpretation mode [release/9.0-staging] Fix to #35208 - Query/Perf: don't compile liftable constant resolvers in interpretation mode Nov 26, 2024
@ajcvickers
Copy link
Contributor

ajcvickers commented Nov 26, 2024

I've looked at this and I don't think I'm ready to approve yet. I think we really need to understand what, "if the final product is itself a delegate, that delegate will itself be in the interpreter mode and therefore less efficient when invoked multiple times when the query runs" really means.

@ajcvickers
Copy link
Contributor

Taked to @roji and I am approving here, but we really need to understand this better.

@maumar maumar added this to the 9.0.x milestone Nov 26, 2024
@maumar maumar merged commit b50581a into release/9.0-staging Nov 27, 2024
7 checks passed
@maumar maumar deleted the fix35208_90 branch November 27, 2024 00:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants