C # findAll VS Where Velocidad
Cualquiera conoce las diferencias de velocidad entre Where y findAll en la lista. Sé dónde es parte deumumerable y findAll es parte de List, solo tengo curiosidad por saber qué es más rápido.
5 answers
El método findAll de la clase List
Dado un conjunto pequeño, los dos probablemente se desempeñarían de manera comparable. Sin embargo, dado un conjunto más grande, Donde debe superar a findAll, como la nueva Lista creada para contener los resultados tendrá que crecer dinámicamente para contener resultados adicionales. El uso de memoria de findAll también comenzará a crecer exponencialmente a medida que aumenta el número de resultados coincidentes, donde como Donde debería tener un uso de memoria mínimo constante (en y por sí mismo...excluyendo lo que hagas con los resultados.)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-14 05:31:31
FindAll es obviamente más lento que Where, porque necesita crear una nueva lista.
De todos modos, creo que realmente debería considerar el comentario de Jon Hanna: probablemente necesitará hacer algunas operaciones en sus resultados y la lista sería más útil queumumerable en muchos casos.
Escribí una pequeña prueba, solo pégala en el proyecto de la aplicación de consola. Mide el tiempo / ticks de: ejecución de funciones, operaciones en la colección de resultados (para obtener perf. de uso 'real' , y para estar seguro de que el compilador no optimizar los datos no utilizados, etc. - Soy nuevo en C# y no sé cómo funciona todavía,lo siento).
Aviso: cada función medida excepto WhereIENumerable() crea una nueva Lista de elementos. Puede que esté haciendo algo mal, pero claramente iterarerableumerable toma mucho más tiempo que iterar list.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace Tests
{
public class Dummy
{
public int Val;
public Dummy(int val)
{
Val = val;
}
}
public class WhereOrFindAll
{
const int ElCount = 20000000;
const int FilterVal =1000;
const int MaxVal = 2000;
const bool CheckSum = true; // Checks sum of elements in list of resutls
static List<Dummy> list = new List<Dummy>();
public delegate void FuncToTest();
public static long TestTicks(FuncToTest function, string msg)
{
Stopwatch watch = new Stopwatch();
watch.Start();
function();
watch.Stop();
Console.Write("\r\n"+msg + "\t ticks: " + (watch.ElapsedTicks));
return watch.ElapsedTicks;
}
static void Check(List<Dummy> list)
{
if (!CheckSum) return;
Stopwatch watch = new Stopwatch();
watch.Start();
long res=0;
int count = list.Count;
for (int i = 0; i < count; i++) res += list[i].Val;
for (int i = 0; i < count; i++) res -= (long)(list[i].Val * 0.3);
watch.Stop();
Console.Write("\r\n\nCheck sum: " + res.ToString() + "\t iteration ticks: " + watch.ElapsedTicks);
}
static void Check(IEnumerable<Dummy> ieNumerable)
{
if (!CheckSum) return;
Stopwatch watch = new Stopwatch();
watch.Start();
IEnumerator<Dummy> ieNumerator = ieNumerable.GetEnumerator();
long res = 0;
while (ieNumerator.MoveNext()) res += ieNumerator.Current.Val;
ieNumerator=ieNumerable.GetEnumerator();
while (ieNumerator.MoveNext()) res -= (long)(ieNumerator.Current.Val * 0.3);
watch.Stop();
Console.Write("\r\n\nCheck sum: " + res.ToString() + "\t iteration ticks :" + watch.ElapsedTicks);
}
static void Generate()
{
if (list.Count > 0)
return;
var rand = new Random();
for (int i = 0; i < ElCount; i++)
list.Add(new Dummy(rand.Next(MaxVal)));
}
static void For()
{
List<Dummy> resList = new List<Dummy>();
int count = list.Count;
for (int i = 0; i < count; i++)
{
if (list[i].Val < FilterVal)
resList.Add(list[i]);
}
Check(resList);
}
static void Foreach()
{
List<Dummy> resList = new List<Dummy>();
int count = list.Count;
foreach (Dummy dummy in list)
{
if (dummy.Val < FilterVal)
resList.Add(dummy);
}
Check(resList);
}
static void WhereToList()
{
List<Dummy> resList = list.Where(x => x.Val < FilterVal).ToList<Dummy>();
Check(resList);
}
static void WhereIEnumerable()
{
Stopwatch watch = new Stopwatch();
IEnumerable<Dummy> iEnumerable = list.Where(x => x.Val < FilterVal);
Check(iEnumerable);
}
static void FindAll()
{
List<Dummy> resList = list.FindAll(x => x.Val < FilterVal);
Check(resList);
}
public static void Run()
{
Generate();
long[] ticks = { 0, 0, 0, 0, 0 };
for (int i = 0; i < 10; i++)
{
ticks[0] += TestTicks(For, "For \t\t");
ticks[1] += TestTicks(Foreach, "Foreach \t");
ticks[2] += TestTicks(WhereToList, "Where to list \t");
ticks[3] += TestTicks(WhereIEnumerable, "Where Ienum \t");
ticks[4] += TestTicks(FindAll, "FindAll \t");
Console.Write("\r\n---------------");
}
for (int i = 0; i < 5; i++)
Console.Write("\r\n"+ticks[i].ToString());
}
}
class Program
{
static void Main(string[] args)
{
WhereOrFindAll.Run();
Console.Read();
}
}
}
Results (ticks) - CheckSum habilitado(algunas operaciones en los resultados), modo: release without debugging(CTRL+F5):
- 16222276 (para ->lista)
- 17151121 (foreach - >list)
- 4741494 (donde ->lista)
- 27122285 (donde->enum)
- 18821571 (findall ->list)
CheckSum deshabilitado (no se usa la lista devuelta en absoluto):
- 10885004 (para ->lista)
- 11221888 (foreach ->list)
- 18688433 (donde ->lista)
- 1075 (donde->enum)
- 13720243 (findall ->list)
Sus resultados pueden ser ligeramente diferentes, para obtener resultados reales necesita más iteraciones.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-23 11:41:39
.FindAll()
debería ser más rápido, se aprovecha de conocer ya el tamaño de la Lista y loopear a través de la matriz interna con un simple bucle for
. .Where()
tiene que encender un enumerador (una clase de framework sellado llamada WhereIterator
en este caso) y hacer el mismo trabajo de una manera menos específica.
Tenga en cuenta, sin embargo, que .Donde () es enumerable, no creando activamente una Lista en memoria y llenándola. Es más como un flujo, por lo que el uso de memoria en algo muy grande puede tener un significativo diferencia. También, usted podría comenzar a utilizar los resultados de una manera paralela mucho más rápido usando allí .Donde () aproximación en 4.0.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-14 05:32:33
Where
es mucho, mucho más rápido que FindAll
. No importa cuán grande sea la lista, Where
toma exactamente la misma cantidad de tiempo.
Por supuesto, Where
simplemente crea una consulta. En realidad no hace nada, a diferencia de FindAll
que crea una lista.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-02 13:12:53
La respuesta de jrista hace sentido. Sin embargo, la nueva lista agrega los mismos objetos, por lo que solo crece con referencia a los objetos existentes, que no deberían ser tan lentos. Siempre y cuando la extensión 3.5 / Linq sea posible, Donde se mantiene mejor de todos modos. findAll tiene mucho más sentido cuando está limitado con 2.0
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-15 12:31:41