我正在做一些性能测试,发现LINQ表达式像
result = list.First(f => f.Id == i).Property
比慢
result = list.Where(f => f.Id == i).First().Property
这似乎与直觉相反。我以为第一个表达式会更快,因为一旦满足谓词,它就可以停止对列表进行迭代,而我以为该.Where()
表达式可以在调用.First()
结果子集之前对整个列表进行迭代。即使后者短路,也不应比直接使用First更快。
下面是两个非常简单的单元测试,它们说明了这一点。当在.NET和Silverlight 4上使用TestWhereAndFirst进行优化编译时,其速度大约比TestFirstOnly快30%。我试图使谓词返回更多结果,但是性能差异是相同的。
谁能解释为什么.First(fn)
比它慢.Where(fn).First()
?与.Count(fn)
相比,我看到了类似的反直观结果.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);
}
First()
调用LINQ时 ,它将仅查询(Where(...)
一个)匹配项(的返回值),而从不要求另一个匹配项。因此,将检查与调用时完全相同数量的元素First(...)
(即直接使用谓词)。