订购的LINQ扩展方法不会影响性能? [英] Order of LINQ extension methods does not affect performance?

查看:145
本文介绍了订购的LINQ扩展方法不会影响性能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很惊讶,它显然并不重要,我是否prePEND或追加LINQ扩展方法。

测试与<一个href="http://msdn.microsoft.com/en-us/library/bb340482.aspx"><$c$c>Enumerable.FirstOrDefault:

  1. hugeList.Where(X =&GT; x.Text.Contains(10000))FirstOrDefault();
  2. hugeList.FirstOrDefault(X =&GT; x.Text.Contains(10000));

      VAR hugeList = Enumerable.Range(1,5000)
        。选择(I =&gt;新建{ID = I,文本=项目+ I});
    
    VAR SW1 =新System.Diagnostics.Stopwatch();
    VAR SW2 =新System.Diagnostics.Stopwatch();
    
    sw1.Start();
    的for(int i = 0; I&LT; 1000;我++)
        hugeList.Where(X =&GT; x.Text.Contains(10000))。FirstOrDefault();
    sw1.Stop();
    
    sw2.Start();
    的for(int i = 0; I&LT; 1000;我++)
        hugeList.FirstOrDefault(X =&GT; x.Text.Contains(10000));
    sw2.Stop();
    
    VAR RESULT1 =的String.Format(FirstOrDefault后:{0} FirstOrDefault前:{1},sw1.Elapsed,sw2.Elapsed);
    // RESULT1:FirstOrDefault后:00:00:03.3169683 FirstOrDefault前:00:00:03.0463219
    
    sw2.Restart();
    的for(int i = 0; I&LT; 1000;我++)
        hugeList.FirstOrDefault(X =&GT; x.Text.Contains(10000));
    sw2.Stop();
    
    sw1.Restart();
    的for(int i = 0; I&LT; 1000;我++)
        hugeList.Where(X =&GT; x.Text.Contains(10000))。FirstOrDefault();
    sw1.Stop();
    
    VAR结果2 =的String.Format(FirstOrDefault之前:{0} FirstOrDefault后:{1},sw2.Elapsed,sw1.Elapsed);
    //结果2:FirstOrDefault前:00:00:03.6833079 FirstOrDefault后:00:00:03.1675611
    
    //平均后:3.2422647前:3.3648149(均秒)
     

我也能猜到,这将是慢prePEND 其中,,因为它必须找到所有匹配的项目,然后把第一和preceded FirstOrDefault 可能产生的第一个找到的项目。

问:有人可以解释为什么我在错误的轨道上?

解决方案
  

我也能猜到,这将是慢prePEND哪里,因为它必须找到所有匹配的项目,然后把第一和preceded FirstOrDefault可能会产生的第一个找到的项目。有人可以解释为什么我在错误的轨道上?

你是在错误的轨道上,因为你的第一个说法是根本不正确。 其中,没有的发现之前的所有匹配项的获取第一个匹配项要求。 其中,取随需应变的配套项目;如果你只要求第一个,只取第一个。如果你只要求前两个,只取前两种。

乔恩斯基特确实在舞台上一个不错位。想象一下,你有三个人。第一个人拥有的卡洗牌包。第二种人有T恤,上面写着凡卡是红色的。第三人捅第二个人说给我的第一张牌。第二个人戳的第一人一遍又一遍的的第一人递过一张红牌,然后再由第二个人手中的第三人。第二个人没有任何理由继续戳的第一人;任务完成了!

现在,如果第二个人的T恤说:为了通过等级上升,那么,我们有一个非常不同的情况。现在第二个人确实需要得到每一张牌的第一人,为了找到最低卡在甲板上,发放了第一张牌给第三人面前。

这应该现在给你必要的直觉告诉时候为了做事情出于性能的考虑。的最终结果给我红牌,然后对其进行排序是完全一样之类的所有的牌,然后给我红色的,但前者是更快,因为你不必花费任何时间排序黑卡,你会放弃。

I'm surprised that it apparently doesn't matter whether i prepend or append LINQ extension methods.

Tested with Enumerable.FirstOrDefault:

  1. hugeList.Where(x => x.Text.Contains("10000")).FirstOrDefault();
  2. hugeList.FirstOrDefault(x => x.Text.Contains("10000"));

    var hugeList = Enumerable.Range(1, 50000000)
        .Select(i => new { ID = i, Text = "Item" + i });
    
    var sw1 = new System.Diagnostics.Stopwatch();
    var sw2 = new System.Diagnostics.Stopwatch();
    
    sw1.Start();
    for(int i=0;i<1000;i++)
        hugeList.Where(x => x.Text.Contains("10000")).FirstOrDefault();
    sw1.Stop();
    
    sw2.Start();
    for(int i=0;i<1000;i++)
        hugeList.FirstOrDefault(x => x.Text.Contains("10000"));
    sw2.Stop();
    
    var result1 = String.Format("FirstOrDefault after: {0} FirstOrDefault before: {1}", sw1.Elapsed,  sw2.Elapsed);
    //result1: FirstOrDefault after: 00:00:03.3169683 FirstOrDefault before: 00:00:03.0463219
    
    sw2.Restart();
    for (int i = 0; i < 1000; i++)
        hugeList.FirstOrDefault(x => x.Text.Contains("10000"));
    sw2.Stop();
    
    sw1.Restart();
    for (int i = 0; i < 1000; i++)
        hugeList.Where(x => x.Text.Contains("10000")).FirstOrDefault();
    sw1.Stop();
    
    var result2 = String.Format("FirstOrDefault before: {0} FirstOrDefault after: {1}", sw2.Elapsed, sw1.Elapsed);
    //result2: FirstOrDefault before: 00:00:03.6833079 FirstOrDefault after: 00:00:03.1675611
    
    //average after:3.2422647 before: 3.3648149 (all seconds)
    

I would have guessed that it would be slower to prepend Where since it must find all matching items and then take the first and a preceded FirstOrDefault could yield the first found item.

Q: Can somebody explain why i'm on the wrong track?

解决方案

I would have guessed that it would be slower to prepend Where since it must find all matching items and then take the first and a preceded FirstOrDefault could yield the first found item. Can somebody explain why i'm on the wrong track?

You are on the wrong track because your first statement is simply incorrect. Where is not required to find all matching items before fetching the first matching item. Where fetches matching items "on demand"; if you only ask for the first one, it only fetches the first one. If you only ask for the first two, it only fetches the first two.

Jon Skeet does a nice bit on stage. Imagine you have three people. The first person has a shuffled pack of cards. The second person has a t-shirt that says "where card is red". The third person pokes the second person and says "give me the first card". The second person pokes the first person over and over again until the first person hands over a red card, which the second person then hands to the third person. The second person has no reason to keep poking the first person; the task is done!

Now, if the second person's t-shirt says "order by rank ascending" then we have a very different situation. Now the second person really does need to get every card from the first person, in order to find the lowest card in the deck, before handing the first card to the third person.

This should now give you the necessary intuition to tell when order does matter for performance reasons. The net result of "give me the red cards and then sort them" is exactly the same as "sort all the cards then give me the red ones", but the former is much faster because you do not have to spend any time sorting the black cards that you are going to discard.

这篇关于订购的LINQ扩展方法不会影响性能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆