c# performance linq foreach

c# - ¿Es una declaración LINQ más rápida que un bucle ''foreach''?



linq vs foreach c# (8)

¿Por qué LINQ debería ser más rápido? También usa bucles internamente.

La mayoría de las veces, LINQ será un poco más lento porque introduce una sobrecarga. No use LINQ si le importa mucho el rendimiento. Use LINQ porque quiere un código más corto, legible y fácil de mantener.

Estoy escribiendo un administrador de Mesh Rendering y pensé que sería una buena idea agrupar todas las mallas que usan el mismo sombreador y luego renderizarlas mientras estoy en ese paso de sombreado.

Actualmente estoy usando un bucle foreach , pero me preguntaba si la utilización de LINQ podría darme un aumento en el rendimiento.


Creo que es mejor usar LINQ en un bucle foreach , porque te da un código mucho más limpio y fácil de entender. Pero LINQ es más lento que foreach . Para obtener más, consulte el artículo LINQ vs FOREACH vs FOR Loop Performance .


Es posible que obtenga un aumento de rendimiento si utiliza LINQ paralelo para múltiples núcleos. Ver Parallel LINQ (PLINQ) (MSDN).


Esta es en realidad una pregunta bastante compleja. Linq hace ciertas cosas muy fáciles de hacer, que si las implementa usted mismo, puede tropezar con (por ejemplo, linq. Except ()). Esto se aplica particularmente a PLinq, y especialmente a la agregación paralela según lo implementado por PLinq.

En general, para código idéntico, linq será más lento, debido a la sobrecarga de la invocación de delegado.

Sin embargo, si está procesando una gran cantidad de datos y aplicando cálculos relativamente simples a los elementos, obtendrá un gran aumento en el rendimiento si:

  1. Usas una matriz para almacenar los datos.
  2. Utiliza un ciclo for para acceder a cada elemento (a diferencia de foreach o linq).

    • Nota: cuando se comparta, todos deben recordar: si usa la misma matriz / lista para dos pruebas consecutivas, la memoria caché de la CPU hará que la segunda sea más rápida. *

Estaba interesado en esta pregunta, así que hice una prueba en este momento. Usando .NET Framework 4.5.2 en una CPU Intel (R) Core (TM) i3-2328M a 2.20GHz, 2200 Mhz, 2 Core (s) con 8GB de memoria RAM con Microsoft Windows 7 Ultimate.

Parece que LINQ podría ser más rápido que para cada ciclo. Aquí están los resultados que obtuve:

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

Sería interesante que algunos de ustedes pudieran copiar y pegar este código en una aplicación de consola y probarlo también. Antes de probar con un objeto (Empleado) Probé la misma prueba con enteros. LINQ fue más rápido allí también.

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 }


LINQ ahora es más lento, pero puede ser más rápido en algún momento. Lo bueno de LINQ es que no tiene que preocuparse por cómo funciona. Si se piensa en un nuevo método que es increíblemente rápido, la gente de Microsoft puede implementarlo sin siquiera decírselo y su código sería mucho más rápido.

Sin embargo, lo más importante es que LINQ es mucho más fácil de leer. Esa debería ser suficiente razón.


LINQ-to-Objects generalmente va a agregar algunos gastos indirectos marginales (iteradores múltiples, etc.). Todavía tiene que hacer los bucles, y tiene invocaciones de delegado, y generalmente tendrá que hacer una desreferenciación adicional para obtener las variables capturadas, etc. En la mayoría de los códigos esto será virtualmente indetectable, y más que el código más simple de entender.

Con otros proveedores de LINQ como LINQ-to-SQL, dado que la consulta puede filtrar en el servidor, debería ser mucho mejor que un foreach plano, pero lo más probable es que no hubiera hecho una manta "select * from foo" todos modos , eso no es necesariamente una comparación justa.

Re PLINQ; el paralelismo puede reducir el tiempo transcurrido , pero el tiempo total de la CPU por lo general aumentará un poco debido a los gastos generales de administración de subprocesos, etc.