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 |
Example comparer lambda we generate in EF9 for PopulateIncludeCollection method:
Instead we should inline the inner lambda like so:
This change yields significant improvement for Include collection scenarios with large number of elements:
ef 9 before the Invoke fix
ef 9 after the invoke fix