Reduce lambda compilation for constant evaluation #375
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.
Motivation
We are seeing significant, ongoing JIT compilations and allocations as a result of evaluating constants during the query generation process. Almost all queries include some reference to a local variable as part of the expression tree, such as a reference to the IQueryable itself or a filter variable in a Where predicate. These local variables are captured as a closure by C# under the covers, and appear as MemberAccessExpression with a ConstantExpression as the target. Currently, such cases require the JIT compilation of a lambda for every single execution of the query.
Modifications
Create an EnhancedPartialEvaluatingExpressionTreeVisitor based upon the Relinq PartialEvaluatingExpressionTreeVisitor that evaluates more cases using reflection instead of compiling a lambda. This includes the mentioned member access case as well as some other common cases. Expressions which can't be evaluated in this manner fallback to the previous behavior of compiling a lambda and executing it.
Results
Significantly less overhead for most queries when computing the constant portions of the query. Note that in this context constant means a the portion of the query that is known and evaluatable within C# without requiring data from the database. It does not necessarily mean that the values are constant for each execution of the query.