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

Nei*_*ght 111 c# linq performance foreach

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

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

cod*_*nix 198

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

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

  • 我觉得你倒退了.他说LINQ是SLOWER.这是由于头脑发热.他还说LINQ更易于阅读和维护. (81认同)
  • 老实说,foreach循环比LINQ方法更具可读性.我使用LINQ,因为它很酷:) (28认同)
  • 那么您的体验是LINQ更快,并且使代码更难以阅读和维护?请解释. (6认同)
  • 抱歉.与此同时,我们在很多方面比较了linq和foreach性能,而且大多数时候linq更快. (4认同)
  • 是的,但在某些情况下LINQ可能真的提高了可读性,所以忘记我的无意见的评论<3 (3认同)
  • foreach 循环实际上比 LINQ 更容易阅读。它也更快、更容易调试。为什么要使用 LINQ foreach? (2认同)

Mar*_*ell 56

LINQ-to-Objects 通常会增加一些边际开销(多个迭代器等).它仍然必须执行循环,并且具有委托调用,并且通常必须进行一些额外的解除引用以获取捕获的变量等.在大多数代码中,这几乎是不可检测的,并且通过更简单的理解代码提供了更多.

与其他LINQ提供像LINQ到SQL,则因为查询可以在服务器过滤应该是很多更好的比持平foreach,但很有可能你不会做毯子"select * from foo" 无论如何,所以这不是一定公平比较.

重新PLINQ; 并行性可以减少经过的时间,但是由于线程管理等的开销,总CPU时间通常会略微增加.


Pra*_*ana 18

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


Jou*_*aas 15

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

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

  • 我喜欢"微软可以实现它"这一行是否有可能,我的意思是,如果没有我升级框架可能吗? (3认同)
  • LINQ 永远不会比本机实现更快,因为在一天结束时,它会转换为本机实现。没有特殊的 LINQ CPU 指令和 LINQ 寄存器可用于转换更快的 LINQ 机器代码——如果有,它们也会被非 LINQ 代码使用。 (2认同)

pee*_*otA 10

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

参考: 在.NET中,哪个循环运行得更快,'for'或'foreach'?


mci*_*321 9

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


The*_*nd. 7

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

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

Exists = True
Time   = 174
Exists = True
Time   = 149
Run Code Online (Sandbox Code Playgroud)

如果你们中的一些人可以将此代码复制并粘贴到控制台应用程序中并进行测试,那将会很有趣。在使用对象(员工)进行测试之前,我尝试使用整数进行相同的测试。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

}
Run Code Online (Sandbox Code Playgroud)

  • 有趣的。我得到 `Exists=True Time=184 Exists=True Time=135` 它位于 Apache Gaming 笔记本电脑上(Win 10,C# 7.3)。编译并在调试模式下运行。如果我反转测试,我会得到 `Exists=True Time=158 Exists=True Time=194`。我猜似乎 Linq 更加优化了。 (4认同)
  • 你有没有考虑过先做 linq,然后再做 foreach,它也可能会有所不同 (2认同)
  • 所有这些不准确的答案和评论。不,“LINQ”迭代器现在不会、也永远不会比“foreach”更快。另外,“List.Exists”**不是** LINQ 方法。 (2认同)