LINQ语句比'foreach'循环更快吗?

时间:2010-07-01 08:18:16

标签: c# performance linq foreach

我正在编写一个网格渲染管理器,并认为将所有使用相同着色器的网格分组然后在我使用该着色器时渲染这些网格是个好主意。

我目前正在使用foreach循环,但是想知道利用LINQ是否会让我的性能提升?

8 个答案:

答案 0 :(得分:183)

LINQ为什么要更快?它还在内部使用循环。

大多数情况下,LINQ会慢一点,因为它会引入开销。如果您非常关心性能,请不要使用LINQ。使用LINQ是因为您需要更短的更易读和可维护的代码。

答案 1 :(得分:55)

LINQ-to-Objects 通常将增加一些边际开销(多个迭代器等)。它仍然必须执行循环,具有委托调用,通常必须进行一些额外的解除引用以获取捕获的变量等。在大多数代码中,这将是虚拟的不易察觉,而超过由更简单易懂的代码提供。

对于其他LINQ提供程序,如LINQ-to-SQL,那么由于查询可以在服务器上进行过滤,因此它应该比<{1}}更好 ,但很可能你不会无论如何都已经完成了foreach ,因此

Re PLINQ;并行性可能会减少过去的时间,但由于线程管理的开销等,总CPU时间通常会略有增加。

答案 2 :(得分:15)

我认为LINQ最好在foreach循环中使用,因为它为您提供了更清晰易懂的代码。但是LINQ慢于foreach。要获得更多信息,请查看文章 LINQ vs FOREACH vs FOR Loop Performance

答案 3 :(得分:14)

现在LINQ速度较慢,但​​在某些时候可能会变得更快。 LINQ的好处是你不必关心它是如何工作的。如果想出一种速度非常快的新方法,那么微软的人们甚至可以在不告诉你的情况下实现它,而且你的代码会更快。

更重要的是,LINQ更容易阅读。这应该是足够的理由。

答案 4 :(得分:10)

应该注意for循环比foreach更快。因此,对于原始帖子,如果您担心像渲染器这样的关键组件的性能,请使用for循环。

参考: In .NET, which loop runs faster, 'for' or 'foreach'?

答案 5 :(得分:9)

如果将并行LINQ用于多核,则可能会提高性能。请参阅 Parallel LINQ (PLINQ) (MSDN)。

答案 6 :(得分:3)

这实际上是一个非常复杂的问题。 Linq使某些事情变得非常容易,如果你自己实现它们,你可能会偶然发现(例如linq .Except())。这尤其适用于PLinq,尤其适用于PLinq实现的并行聚合。

通常,对于相同的代码,由于委托调用的开销,linq会更慢。

但是,如果您正在处理大量数据,并对元素应用相对简单的计算,那么在以下情况下您将获得巨大的性能提升:

  1. 您使用数组存储数据。
  2. 使用for循环访问每个元素(与foreach或linq相反)。

    • 注意:在进行基准测试时,请大家记住 - 如果您使用相同的阵列/列表进行两次连续测试,CPU缓存将使第二个更快。 *

答案 7 :(得分:2)

我对这个问题很感兴趣,所以我刚刚做了一个测试。在Intel(R)Core(TM)i3-2328M CPU上使用.NET Framework 4.5.2 @ 2.20GHz,2200 Mhz,2 Core(s),8GB内存运行Microsoft Windows 7 Ultimate。

看起来LINQ可能比每个循环更快。以下是我得到的结果:

Exists = True
Time   = 174
Exists = True
Time   = 149

如果你们中的一些人可以复制和将此代码粘贴到控制台应用程序中并进行测试。 在使用对象(Employee)进行测试之前,我尝试使用整数进行相同的测试。 LINQ在那里也更快。

public class Program
{
    public class Employee
    {
        public int id;
        public string name;
        public string lastname;
        public DateTime dateOfBirth;

        public Employee(int id,string name,string lastname,DateTime dateOfBirth)
        {
            this.id = id;
            this.name = name;
            this.lastname = lastname;
            this.dateOfBirth = dateOfBirth;

        }
    }

    public static void Main() => StartObjTest();

    #region object test

    public static void StartObjTest()
    {
        List<Employee> items = new List<Employee>();

        for (int i = 0; i < 10000000; i++)
        {
            items.Add(new Employee(i,"name" + i,"lastname" + i,DateTime.Today));
        }

        Test3(items, items.Count-100);
        Test4(items, items.Count - 100);

        Console.Read();
    }


    public static void Test3(List<Employee> items, int idToCheck)
    {

        Stopwatch s = new Stopwatch();
        s.Start();

        bool exists = false;
        foreach (var item in items)
        {
            if (item.id == idToCheck)
            {
                exists = true;
                break;
            }
        }

        Console.WriteLine("Exists=" + exists);
        Console.WriteLine("Time=" + s.ElapsedMilliseconds);

    }

    public static void Test4(List<Employee> items, int idToCheck)
    {

        Stopwatch s = new Stopwatch();
        s.Start();

        bool exists = items.Exists(e => e.id == idToCheck);

        Console.WriteLine("Exists=" + exists);
        Console.WriteLine("Time=" + s.ElapsedMilliseconds);

    }

    #endregion


    #region int test
    public static void StartIntTest()
    {
        List<int> items = new List<int>();

        for (int i = 0; i < 10000000; i++)
        {
            items.Add(i);
        }

        Test1(items, -100);
        Test2(items, -100);

        Console.Read();
    }

    public static void Test1(List<int> items,int itemToCheck)
    {

        Stopwatch s = new Stopwatch();
        s.Start();

        bool exists = false;
        foreach (var item in items)
        {
            if (item == itemToCheck)
            {
                exists = true;
                break;
            }
        }

        Console.WriteLine("Exists=" + exists);
        Console.WriteLine("Time=" + s.ElapsedMilliseconds);

    }

    public static void Test2(List<int> items, int itemToCheck)
    {

        Stopwatch s = new Stopwatch();
        s.Start();

        bool exists = items.Contains(itemToCheck);

        Console.WriteLine("Exists=" + exists);
        Console.WriteLine("Time=" + s.ElapsedMilliseconds);

    }

    #endregion

}