简体   繁体   中英

Why is this Linq expression so much slower than the other?

Time of execution: foo(1) >>> foo(2) >> foo(3)

roughly: 1427349 >>> 14757 >> 1362

foo(3) is the most optimized algorithm among the three, so I'm not surprised it's the fastest. What's surprising to me is that foo(2) is so much faster than foo(1). My impression is that foo(2) sorts, while foo(1) is operating similarly to foo(3). May I know what is the cause the slowdown for foo(1)? Show me what's under the hood. Thanks!

void Main()
{   
    Random r = new Random();
    for(int i = 0; i < array.Length; i++)
    {
        array[i] = new A(r.Next(int.MaxValue));
    }   

    foo(1); 
    foo(2);
    foo(3); 
}

A[] array = new A[10000];
static Stopwatch sw = new Stopwatch();

public void foo(int s)
{
    sw.Reset();
    sw.Start();

    switch(s)
    {
        case 1:
            array.First(x => (x.value == array.Max(y => y.value))).Dump();
            break;
        case 2:
            array.OrderBy(x => x.value)
            .Last()
            .Dump();    
            break;
        case 3:
            {           
                int max = array[0].value;
                int index = 0;
                int i = 0;
                for(; i < array.Length; i++)
                {
                    if(array[i].value >= max)
                    {
                        max = array[i].value;
                        index = i;
                    }
                }
                array[index].Dump();
            }
            break;
    }

    sw.Stop();
    sw.Dump();
}
class A
{
    public int value;
    public A(int value)
    {
        this.value = value;
    }
}

Code testing was in linqpad, so you can ignore the .Dump() method.

The first is O(N²), because you iterate over the array once for each outer iteration. The second is O(N log N), because you are sorting first. The last is O(N), because you iterate over the array in a single pass with no loop inside each iteration.

Try this:

        case 1:
            var max = array.Max(x => x.value);
            array.First(x => x.value == max).Dump();
            break;

It should now be comparable with the third case, though not quite, since you have to traverse the array 1.5 times, on average (assuming only one element has the max value).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM