hazzik / DelegateDecompiler

A library which is able to decompile a delegate or a method body to its lambda representation
MIT License
522 stars 62 forks source link

Performance regression from 0.31.0 to 0.32.0 #220

Open NetMastr5 opened 11 months ago

NetMastr5 commented 11 months ago

When applying a where clause that has more then ~10 conditions, V0.32.0 is slower then V0.31.0, and this slowness seems to be exponential to the number of conditions in the filter.

This is on .Net Framework 4.8, Entity Framework 6.4.4


locationIds is a list of numbers
LOC.locationId is the primary key

~~~Test Code~~~
Expression<Func<LOC, bool>> filter = UniversalPredicateBuilder.False<LOC>();

foreach (decimal id in locationIds)
    filter = filter.Or(x => x.locationId == id);

var final2 = this.context.LOC.Where(filter);

DateTime now1 = DateTime.Now;
var final3 = final2.Decompile();
Debug.WriteLine($"{i} - {(DateTime.Now - now1).TotalMilliseconds}");
Debug.Flush();

~~~Results~~~
# of IDs in list            V0.32 (ms)  V0.31 (ms)
1                   0           0
2                   0           0
3                   5.9823      0
4                   0           0
5                   0           0
6                   0           0
7                   0           0
8                   0           0
9                   0           0
10                  0.9965      0
11                  0.9963      0
12                  33.9375     0
13                  77.6428     0
14                  176.3968        0
15                  294.0033        0
16                  518.0765        0
17                  74.7487     0
18                  130.652     0
19                  114.7691        0
20                  277.2769        0
21                  520.9336        0
22                  1030.82     0
23                  2042.5927   0
24                  3369.2147   0
25                  7161.9973   0
26                  12517.4393  0
27                  24512.0805  0
28                  47910.7318  0.9965
29                  94613.1383  0
30                  188813.2178 0

~~~Other Notes~~~
this.context.LOC.Where(x => locationIds.Contains(x.locationId)) has the same performance between V0.31 and V0.32
Breaking up the filter into parts limits the effect to the size of an individual filter level
        Expression<Func<LOC, bool>> filter1 = UniversalPredicateBuilder.False<LOC>();
        foreach (decimal id in locationIds.Take(10))
            filter1 = filter1.Or(x => x.locationId == id);

        Expression<Func<LOC, bool>> filter2 = UniversalPredicateBuilder.False<LOC>();
        foreach (decimal id in locationIds.Skip(10).Take(10))
            filter2 = filter2.Or(x => x.locationId == id);

        Expression<Func<LOC, bool>> filter3 = UniversalPredicateBuilder.False<LOC>();
        foreach (decimal id in locationIds.Skip(20))
            filter3 = filter3.Or(x => x.locationId == id);

        Expression<Func<LOC, bool>> filter = UniversalPredicateBuilder.False<LOC>();

        filter = filter
            .Or(filter1)
            .Or(filter2)
            .Or(filter3);

        var final2 = this.context.LOC.Where(filter);

        DateTime now1 = DateTime.Now;
        var final3 = final2.Decompile();
        Debug.WriteLine($"{i} - {(DateTime.Now - now1).TotalMilliseconds}");
        Debug.Flush();