Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么在本例中LINQ更快_C#_Performance_Linq_Foreach - Fatal编程技术网

C# 为什么在本例中LINQ更快

C# 为什么在本例中LINQ更快,c#,performance,linq,foreach,C#,Performance,Linq,Foreach,我编写了以下代码来测试使用foreachvsLINQ的性能: 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++

我编写了以下代码来测试使用
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();
}
私有类小部件
{
公共字符串名称{get;set;}
}
静态void Main(字符串[]参数)
{
列表小部件=新列表();
int=0;
对于(int i=0;i a.Name.StartsWith(“4”)).Count();
Console.WriteLine(find+“-”+DateTime.Now.Subtract(starttime.millides+“ms”);
Console.ReadLine();
}
我得到如下输出:

31160 - 116ms 31160 - 95 ms 31160-116ms 31160-95毫秒 在每一轮中,LINQ的表现都比foreach好20%左右。据我所知,LINQ扩展方法在封面下使用了标准c#

那么为什么在这种情况下LINQ更快呢

编辑:


因此,我将代码改为使用秒表而不是datetime,仍然得到相同的结果。如果我先运行LINQ查询,那么我的结果显示LINQ比foreach慢大约20%。这一定是某种JIT预热问题。我的问题是如何在我的测试用例中补偿JIT预热?

我不久前做了一些分析,比较了以下几点:

  • LINQ到带/不带正则表达式的对象

  • 带/不带正则表达式的Lambda表达式

  • 带/不带正则表达式的传统迭代

我发现LINQ、Lambda和传统迭代几乎总是一样的,但真正的时间差异在于正则表达式。只添加正则表达式会使计算速度变慢(慢得多)。(详情如下:)


您在上面看到的可能是由于您在同一代码块中执行两个测试。试着评论一个,计时,然后评论另一个。另外,确保您正在运行发布版本,而不是在调试器中。

这是因为您没有预热。如果您撤销您的案例,您将获得完全相反的结果:

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

你试过颠倒测试顺序吗?您很可能看到了JIT计时。通常最好先运行一次测试来预热系统,然后再运行一次并计时。此外,使用秒表。看,他告诉过你——不定时地运行测试,然后使用Stopwatch类重新运行测试(更准确)。不要忘记在
Release
模式下而不是
Debug
模式下运行。这可能会产生差异。@Coltech要预热代码,只需在开始测试运行之前运行一次,以便在测试运行开始之前对所有调用的方法等进行JIT编译。当我这样做时,我只是在另一个方法中测试代码,然后在我的计时循环之前调用该方法一次,然后在计时循环中调用该方法。您基本上重新表述了Jon Skeet的评论(没有太多细节,“预热”与JIT)。您应该添加示例和更多解释…谢谢。我将用秒表代替日期时间。你能定义一下你所说的“预热”是什么意思吗?你两次都在测试同一种方法,而且你仍然使用DateTime来获取计时……使用这段代码并用秒表替换DateTime产生了预期的结果。谢谢将datetime更改为stopwatch实现这个问题与正则表达式有什么关系?这只是分析示例的一部分。请随意忽略正则表达式部分。