sintaxis query c# .net linq

query - sintaxis linq c#



¿Es el recuento de Linq() más rápido o más lento que List.Count o Array.Length? (7)

Alguna información adicional - Recuento LINQ - la diferencia entre usarlo y no puede ser enorme - y esto no tiene que ser sobre colecciones ''grandes'' tampoco. Tengo una colección formada por linq para objetos con aproximadamente 6500 elementos (grande ... pero no enorme de ninguna manera). Count () en mi caso toma varios segundos. Convirtiendo en una lista (o matriz, qué), el conteo es virtualmente inmediato. Tener esto en cuenta en un bucle interno significa que el impacto podría ser enorme. Count enumera todo. Una matriz y una lista son "autoconscientes" de sus longitudes y no es necesario enumerarlas. Cualquier declaración de depuración (log4net por ejemplo) que haga referencia a este conteo () también ralentizará considerablemente todo. Hágase un favor y si necesita referenciar esto a menudo, guarde el tamaño de conteo y solo llámelo una vez en una colección LINQ a menos que lo convierta en una lista y luego pueda hacer referencia sin un golpe de rendimiento.

Aquí hay una prueba rápida de lo que estaba hablando anteriormente. Nótese que cada vez que llamamos a Count () nuestro tamaño de colección cambia ... por lo tanto, la evaluación ocurre, que es más que una operación de ''recuento'' esperada. Algo de lo que debes tener cuidado:)

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace LinqTest { class TestClass { public TestClass() { CreateDate = DateTime.Now; } public DateTime CreateDate; } class Program { static void Main(string[] args) { //Populate the test class List list = new List(1000); for (int i=0; i<1000; i++) { System.Threading.Thread.Sleep(20); list.Add(new TestClass()); if(i%100==0) { Console.WriteLine(i.ToString() + " items added"); } } //now query for items var newList = list.Where(o=> o.CreateDate.AddSeconds(5)> DateTime.Now); while (newList.Count() > 0) { //Note - are actual count keeps decreasing.. showing our ''execute'' is running every time we call count. Console.WriteLine(newList.Count()); System.Threading.Thread.Sleep(500); } } } }

¿El método Linq Count( ) es más rápido o más lento que List<>.Count o Array.Length ?


Creo que si llama a Linq.Count () en un ICollection o IList (como un ArrayList o List), simplemente devolverá el valor de la propiedad Count. Por lo tanto, el rendimiento será aproximadamente el mismo en las colecciones simples.


El método Enumerable.Count() busca ICollection<T> , utilizando .Count , por lo que en el caso de matrices y listas, no es mucho más ineficiente (solo un nivel adicional de indirección).


En general, más lento. El recuento de LINQ en general es una operación O(N) mientras que List.Count y Array.Length tienen la garantía de ser O(1) .

Sin embargo, en algunos casos, LINQ presentará un caso especial del IEnumerable<T> al IEnumerable<T> a ciertos tipos de interfaz como IList<T> o ICollection<T> . Luego usará ese método Count para hacer una operación real Count() . Entonces volverá a bajar a O(1) . Pero aún pagas la sobrecarga menor del reparto y la llamada a la interfaz.


Marc tiene la respuesta correcta, pero el diablo está en los detalles.

En mi máquina:

  • Para arrays .Length es aproximadamente 100 veces más rápido que .Count ()
  • Para las listas .Count es aproximadamente 10 veces más rápido que .Count () - Nota: esperaría un rendimiento similar de todas las colecciones que implementan IList<T>

Las matrices comienzan más despacio ya que .Length solo implica una sola operación, .Count en matrices implica una capa de indirección. Entonces, .Count en matrices comienza 10 veces más lento (en mi máquina), lo que podría ser una de esas razones por las que la interfaz se implementa explícitamente. Imagine si tuviera un objeto con dos propiedades públicas, .Count y .Length. Ambos hacen exactamente lo mismo pero .Count es 10 veces más lento.

Por supuesto, esto no hace mucha diferencia, ya que tendrías que contar tus matrices y listas millones de veces por segundo para sentir un golpe de rendimiento.

Código:

static void TimeAction(string description, int times, Action func) { var watch = new Stopwatch(); watch.Start(); for (int i = 0; i < times; i++) { func(); } watch.Stop(); Console.Write(description); Console.WriteLine(" Time Elapsed {0} ms", watch.ElapsedMilliseconds); } static void Main(string[] args) { var array = Enumerable.Range(0, 10000000).ToArray(); var list = Enumerable.Range(0, 10000000).ToArray().ToList(); // jit TimeAction("Ignore and jit", 1 ,() => { var junk = array.Length; var junk2 = list.Count; array.Count(); list.Count(); }); TimeAction("Array Length", 1000000, () => { var tmp1 = array.Length; }); TimeAction("Array Count()", 1000000, () => { var tmp2 = array.Count(); }); TimeAction("Array Length through cast", 1000000, () => { var tmp3 = (array as ICollection<int>).Count; }); TimeAction("List Count", 1000000, () => { var tmp1 = list.Count; }); TimeAction("List Count()", 1000000, () => { var tmp2 = list.Count(); }); Console.ReadKey(); }

Resultados:

Array Length Time Elapsed 3 ms Array Count() Time Elapsed 264 ms Array Length through cast Time Elapsed 16 ms List Count Time Elapsed 3 ms List Count() Time Elapsed 18 ms


Yo diría que depende de la Lista. Si es un IQueryable que es una tabla en un db en alguna parte, entonces Count () será mucho más rápido porque no tiene que cargar todos los objetos. Pero si la lista está en memoria, supongo que la propiedad Count sería más rápida si no es igual.


List.Count o Array.Length es de hecho más rápido que Linq Count() . Porque Linq Count() repetirá a través de toda la lista de elementos para contar. List.Count o Array.Length usan su propiedad.