为什么LINQ。凡(predicate)。首先()比。首先(predicate)更快? [英] Why is LINQ .Where(predicate).First() faster than .First(predicate)?

查看:278
本文介绍了为什么LINQ。凡(predicate)。首先()比。首先(predicate)更快?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在做一些性能测试,发现一个LINQ EX pression像

 的结果= list.First(F => f.Id == I).Property
 

 的结果= list.Where(F => f.Id == I)。首先()属性。
 

这似乎有点违背直觉。我本来以为第一八佰伴pression会更快,因为它可以停止遍历列表只要predicate满意,而我本来以为在。凡( ) EX pression可能会遍历整个列表之前调用。首先()的结果子集。即使后者则短路它不应该比使用第一直接更快,但它是。

下面是两个非常简单的单元测试,说明这一点。当与TestWhereAndFirst优化编译比TestFirstOnly更快的.Net和Silverlight 4,约30%的我都试过使得predicate返回更多的结果,但在性能上的差异是一致的。

任何一个可以解释为什么。首先(FN)慢于。凡(FN)。首先()?我看到类似的反直觉的结果与 .Count之间(FN)。凡(FN).Count之间()

 私人const int的范围= 50000;

私有类简单
{
   公众诠释编号{获得;组; }
   公共int值{获得;组; }
}

[测试方法()]
公共无效TestFirstOnly()
{
   名单<简单>名单=新的名单,其中,简单>(范围);
   的for(int i =范围 -  1; I> = 0; --i)
   {
      list.Add(新简{n = I,值= 10});
   }

   INT结果为0;
   的for(int i = 0; I<范围; ++ I)
   {
      结果+ = list.First(F => f.Id == I)。价值;
   }

   Assert.IsTrue(结果大于0);
}

[测试方法()]
公共无效TestWhereAndFirst()
{
   名单<简单>名单=新的名单,其中,简单>(范围);
   的for(int i =范围 -  1; I> = 0; --i)
   {
      list.Add(新简{n = I,值= 10});
   }

   INT结果为0;
   的for(int i = 0; I<范围; ++ I)
   {
      结果+ = list.Where(F => f.Id == I)。首先()值。
   }

   Assert.IsTrue(结果大于0);
}
 

解决方案

我得到了相同的结果:其中+第一比第一快

由于乔恩指出,LINQ的使用延迟计算这样的表现应该是(现在也是)两种方法大致相同。

展望反射器,先用一个简单的foreach循环遍历集合,但如果有多种迭代器专门针对不同类型的集合(数组,列表等)。 presumably这是什么给凡小的优势。

I am doing some performance tests and noticed that a LINQ expression like

result = list.First(f => f.Id == i).Property

is slower than

result = list.Where(f => f.Id == i).First().Property

This seems counter intuitive. I would have thought that the first expression would be faster because it can stop iterating over the list as soon as the predicate is satisfied, whereas I would have thought that the .Where() expression might iterate over the whole list before calling .First() on the resulting subset. Even if the latter does short circuit it should not be faster than using First directly, but it is.

Below are two really simple unit tests that illustrate this. When compiled with optimisation on TestWhereAndFirst is about 30% faster than TestFirstOnly on .Net and Silverlight 4. I have tried making the predicate return more results but the performance difference is the same.

Can any one explain why .First(fn) is slower than .Where(fn).First()? I see a similar counter intuitive result with .Count(fn) compared to .Where(fn).Count().

private const int Range = 50000;

private class Simple
{
   public int Id { get; set; }
   public int Value { get; set; }
}

[TestMethod()]
public void TestFirstOnly()
{
   List<Simple> list = new List<Simple>(Range);
   for (int i = Range - 1; i >= 0; --i)
   {
      list.Add(new Simple { Id = i, Value = 10 });
   }

   int result = 0;
   for (int i = 0; i < Range; ++i)
   {
      result += list.First(f => f.Id == i).Value;
   }

   Assert.IsTrue(result > 0);
}

[TestMethod()]
public void TestWhereAndFirst()
{
   List<Simple> list = new List<Simple>(Range);
   for (int i = Range - 1; i >= 0; --i)
   {
      list.Add(new Simple { Id = i, Value = 10 });
   }

   int result = 0;
   for (int i = 0; i < Range; ++i)
   {
      result += list.Where(f => f.Id == i).First().Value;
   }

   Assert.IsTrue(result > 0);
}

解决方案

I got the same results: where+first was quicker than first.

As Jon noted, Linq uses lazy evaluation so the performance should be (and is) broadly similar for both methods.

Looking in Reflector, First uses a simple foreach loop to iterate through the collection but Where has a variety of iterators specialised for different collection types (arrays, lists, etc.). Presumably this is what gives Where the small advantage.

这篇关于为什么LINQ。凡(predicate)。首先()比。首先(predicate)更快?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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