Skip to content

Query/Perf: don't use Invoke in value comparer ObjectEqualsExpression lambdas #35206

@maumar

Description

@maumar

Example comparer lambda we generate in EF9 for PopulateIncludeCollection method:

parentIdentifierValueComparers: [LIFTABLE Constant: Func<object, object, bool>[] { Func<object, object, bool>, Func<object, object, bool> } | Resolver: _ => new Func<object, object, bool>[]
{ 
    (left, right) => left == null ? right == null : right != null && Invoke((v1, v2) => v1 == v2, (int)left, (int)right), 
    (left, right) => left == null ? right == null : right != null && Invoke((v1, v2) => v1 == v2, (int)left, (int)right) 
}], 

Instead we should inline the inner lambda like so:

parentIdentifierValueComparers: [LIFTABLE Constant: Func<object, object, bool>[] { Func<object, object, bool>, Func<object, object, bool> } | Resolver: _ => new Func<object, object, bool>[]
{ 
    (left, right) => left == null ? right == null : right != null && (int)left == (int)right, 
    (left, right) => left == null ? right == null : right != null && (int)left == (int)right 
}], 

This change yields significant improvement for Include collection scenarios with large number of elements:

ef 9 before the Invoke fix

Method Async Mean Error StdDev Op/s Gen0 Gen1 Allocated
PredicateMultipleIncludes False 322.6 ms 0.97 ms 0.86 ms 3.099 13000.0000 6000.0000 79.48 MB
PredicateMultipleIncludes True 344.9 ms 6.79 ms 6.67 ms 2.899 14000.0000 7000.0000 87.72 MB

ef 9 after the invoke fix

Method Async Mean Error StdDev Op/s Gen0 Gen1 Allocated
PredicateMultipleIncludes False 242.8 ms 2.39 ms 2.12 ms 4.119 8000.0000 5000.0000 51.69 MB
PredicateMultipleIncludes True 263.4 ms 2.21 ms 2.06 ms 3.797 10000.0000 9000.0000 59.93 MB

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions