LINQ语句比“foreach”循环更快吗?

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

我目前正在使用一个foreach循环,但想知道如果使用LINQ可能会使我的性能提高?

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

大多数情况下,LINQ会比较慢,因为它会引入开销。 如果你关心性能,不要使用LINQ。 使用LINQ,因为你想要更短的更好的可读性和可维护的代码。

LINQ到对象通常会增加一些边际开销(多个迭代器等)。 它仍然需要做循环, 并且有委托调用, 并且通常必须做一些额外的解引用来获取被捕获的variables等等。在大多数代码中,这实际上是无法察觉的,并且简单的理解代码更多。

与LINQ到SQL等其他LINQ提供程序一样,那么由于查询可以在服务器上进行过滤,所以它应该比单纯的foreach好得多 ,但是最有可能的是,您不会做一个"select * from foo"不一定是一个公平的比较。

重新PLINQ; 并行可能会减lessstream逝的时间,但总的CPU时间通常会由于线程pipe理等开销而增加一点点。

我认为LINQ最好在foreach循环中使用,因为它给了你更清晰和易于理解的代码。 但LINQ比foreach慢。 要获得更多,请阅读LINQ vs FOREACH vs FOR Loop Performance文章

现在LINQ比较慢,但是在某些时候它可能会变得更快。 关于LINQ的好处是你不必关心它是如何工作的。 如果一个新的方法被认为是非常快的话,那么微软的人们就可以实现它,甚至不用告诉你,你的代码会快得多。

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

如果对多核使用并行LINQ,可能会提高性能。 参见并行LINQ(PLINQ) (MSDN)。

应该注意的是for循环比foreach快。 所以对于原文,如果你担心像渲染器这样的关键组件的性能,请使用for循环。

参考: 在.NET中,哪个循环运行速度更快,“for”或“foreach”?

我对这个问题感兴趣,所以我刚才做了一个testing。 在Intel(R)Core(TM)i3-2328M CPU上使用.NET Framework 4.5.2(2.20GHz,2200 Mhz,2个运行Microsoft Windows 7 Ultimate的8G RAM内核)。

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

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

如果你们中的一些人可以在控制台应用程序中复制和粘贴这些代码并进行testing,那将会很有趣。 在用一个对象(Employee)进行testing之前,我对整数进行了相同的testing。 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 }