我写了以下内容来测试使用foreach
vs LINQ
:
private class Widget
{
public string Name { get; set; }
}
static void Main(string[] args)
{
List<Widget> widgets = new List<Widget>();
int found = 0;
for (int i = 0; i <= 500000 - 1; i++)
widgets.Add(new Widget() { Name = Guid.NewGuid().ToString() });
DateTime starttime = DateTime.Now;
foreach (Widget w in widgets)
{
if (w.Name.StartsWith("4"))
found += 1;
}
Console.WriteLine(found + " - " + DateTime.Now.Subtract(starttime).Milliseconds + " ms");
starttime = DateTime.Now;
found = widgets.Where(a => a.Name.StartsWith("4")).Count();
Console.WriteLine(found + " - " + DateTime.Now.Subtract(starttime).Milliseconds + " ms");
Console.ReadLine();
}
我得到的信息如下:
31160 - 116ms 31160 - 95 ms
在每次运行中,LINQ都比foreach高出约20%。据我所知,LINQ扩展方法使用了标准的c#。
那么为什么LINQ在这种情况下更快?
修改
因此,我将代码更改为使用秒表而不是日期时间,仍然可以获得相同的结果。如果我先运行LINQ查询,那么我的结果显示LINQ比foreach慢约20%。这必须是某种JIT热身问题。我的问题是如何在我的测试用例中补偿JIT热身?
答案 0 :(得分:15)
这是因为你没有热身。如果你扭转案件,你会得到相反的结果:
31272 - 110ms
31272 - 80 ms
开始添加预热并使用秒表以获得更好的计时。
用热身运行测试:
//WARM UP:
widgets.Where(a => a.Name.StartsWith("4")).Count();
foreach (Widget w in widgets)
{
if (w.Name.StartsWith("4"))
found += 1;
}
//RUN Test
Stopwatch stopwatch1 = new Stopwatch();
stopwatch1.Start();
found = widgets.Where(a => a.Name.StartsWith("4")).Count();
stopwatch1.Stop();
Console.WriteLine(found + " - " + stopwatch1.Elapsed);
found = 0;
Stopwatch stopwatch2 = new Stopwatch();
stopwatch2.Start();
foreach (Widget w in widgets)
{
if (w.Name.StartsWith("4"))
found += 1;
}
stopwatch2.Stop();
Console.WriteLine(found + " - " + stopwatch2.Elapsed);
结果:
31039 - 00:00:00.0783508
31039 - 00:00:00.0766299
答案 1 :(得分:2)
我做了一段时间的分析,比较以下内容:
使用/不使用正则表达式的对象的LINQ
带/不带正则表达式的Lambda表达式
带/不带正则表达式的传统迭代
我发现LINQ,Lambda和Traditional迭代总是相同,但真正的时间差异在于Regex表达式。只有添加正则表达式才能使评估更慢(慢一点)。 (详情请见http://www.midniteblog.com/?p=72)
您在上面看到的可能是由于您在同一代码块中进行两项测试。尝试评论一个,计时,然后评论另一个。另外,请确保您正在运行发布版本,而不是在调试器中。