son romualfons romualdfons romuald que las keywords etiquetas description curso .net performance list optimization collections

.net - romualdfons - romualfons



Que es más rápido: borrar la recopilación o crear instancias nuevas (8)

¿qué será más rápido, llamar al método Clear() o crear una `nueva Lista ()?

Esto es imposible de responder. Realmente depende de muchos factores, incluido cuánto tiempo ha existido la colección.

La mejor opción aquí sería:

  1. Haga un perfil de la aplicación y vea si esto realmente importa. Es probable que no haga ninguna diferencia perceptible, en cuyo caso, utilizaría el método que tenga más sentido en términos de cómo piensas de este objeto.

  2. Si no importa, escriba ambos juegos de códigos y mida la diferencia de velocidad (si corresponde).

Desde una perspectiva práctica, llamar a Clear() no reducirá la memoria (utilizada por la propia List<T> ), ya que no reduce la capacidad de la lista, solo elimina los valores que contiene. Crear una nueva List<T> hará que se asigne una nueva lista, lo que a su vez causará más asignaciones con el crecimiento.

Esto, sin embargo, no significa que será más lento; en muchos casos, la reasignación será más rápida ya que es menos probable que promocione las grandes matrices en generaciones de recolección de basura más altas, lo que a su vez puede mantener el proceso de GC mucho más rápido.

Sin conocer su escenario exacto y medirlo en un generador de perfiles, no hay forma de saber cuál es mejor en su escenario.

Tengo un número de listas genéricas en mi código, que tienen decenas o cientos de elementos. A veces necesito rellenar estas listas con otros objetos, así que la pregunta es: ¿qué será más rápido, llamar al método Clear() o crear una new List<T>() ?


Esto dependerá de muchos factores y, a la larga, probablemente no importe (lo suficiente como para contar) en su programa.

Desde msdn docs .Clear() es una operación O (n).

La inicialización de una nueva instancia tendrá su propia sobrecarga así como (si mantiene la colección con la misma longitud, una operación O (n): es decir, n llamadas Add() ).

Realmente, la única manera de probar esto es configurar algunos cronómetros en tu programa y ver cuál es el efecto si realmente crees que vale la pena. Con toda probabilidad; que no vale la pena.

Mi opinión es que si ya ha creado una colección, Clear() , es por eso que hay un método Clear() en primer lugar.


He hecho varias pruebas por mi cuenta. Los resultados (velocidad) son:

  • para listas pequeñas, por ejemplo, 3 elementos, es más rápido crear listas nuevas, pero la diferencia no es grande
  • para 10 o más elementos en promedio, es mejor borrar las listas. Para tipos de valor mucho mejor (por ejemplo, 3-4 veces), para tiempos de valor como 20% mejor.

Pero al final, es mejor perfilar la aplicación y encontrar cuellos de botella para toda la aplicación.


He realizado esta prueba:

private static void Main(string[] args) { int defaultN = 1000; Stopwatch sw = new Stopwatch(); while (true) { Console.WriteLine("Enter test elements number:"); int n; if (!int.TryParse(Console.ReadLine(), out n)) n = defaultN; else defaultN = n; Console.WriteLine($"Test with {n} elements"); List<object> list = Enumerable.Repeat(new object(), n).ToList(); sw.Start(); Clear(list); sw.Stop(); Console.WriteLine("Clear: {0} ms", sw.ElapsedTicks / 10000D); GC.Collect(); GC.WaitForPendingFinalizers(); List<object> list2 = Enumerable.Repeat(new object(), n).ToList(); sw.Restart(); Reinitialize(list2); sw.Stop(); Console.WriteLine("Reinitialize: {0} ms", sw.ElapsedTicks / 10000D); GC.Collect(); GC.WaitForPendingFinalizers(); List<object> list3 = Enumerable.Repeat(new object(), n).ToList(); sw.Restart(); ReinitializeAndCollect(list3); sw.Stop(); Console.WriteLine("ReinitializeAndCollect: {0} ms", sw.ElapsedTicks / 10000D); Console.WriteLine("==="); } } private static List<object> Clear(List<object> list) { list.Clear(); return list; } private static List<object> Reinitialize(List<object> list) => new List<object>(); private static List<object> ReinitializeAndCollect(List<object> list) { list = new List<object>(); GC.Collect(); GC.WaitForPendingFinalizers(); return list; }

Mi conclusión se basa en los resultados de mi procesador Core i3 normal:

En el caso de miles de elementos, es mejor borrar la lista. Es rápido y eficiente en la memoria.

Si la colección tiene más de 100 000 elementos, la reiniciación se vuelve más atractiva. Si después del perfilado cree que hay un cuello de botella aquí, úselo. La reinicialización será muy rápida, pero como muestra la prueba del tercer método, la recolección de basura en el futuro será tan lenta como simplemente borrar la lista.

Entonces, la respuesta breve es: si no perfiló su aplicación, use Clear . Reutilizar objetos es bueno. Si lo hiciste, ya sabes qué hacer.


Si bien esto puede ser frustrante, la respuesta es realmente que no debería importar. La diferencia de tiempo entre los dos será tan pequeña que probablemente no haga ninguna diferencia en su aplicación. Haga lo que conduzca a un código más limpio y comprensible, y trate de no programar microoptimizaciones.


Si sus objetos son tipos de valor, usaría Clear () para reducir las asignaciones futuras de memoria. De lo contrario, ambos enfoques son casi idénticos.


Tal vez estoy haciendo algo fundamentalmente incorrecto aquí, pero al desarrollar una aplicación ASP.NET en C # estoy encontrando una gran diferencia cuando uso Clear () vs. new. Estoy creando una página de estadísticas con gráficos, que tienen series de datos. Para cada gráfico, tengo una sección donde hago esto:

chart = new ChartistChart() { Title = "My fancy chart" }; series = new List<ChartistMetaValue>(); *some code for getting the statistics* chart.Series.Add(series); chartistLineCharts.Add(chart);

luego sigue otro cuadro.

chart = new ChartistChart() { Title = "My second fancy chart" }; series = new List<ChartistMetaValue>(); *some code for getting the statistics* chart.Series.Add(series); chartistLineCharts.Add(chart);

Esto funciona bien con la reasignación de series con new , pero cuando lo hago

series.Clear();

en su lugar, chart.Series la entrada dentro de chart.Series y chartistLineCharts para que la página de estadísticas termine recuperando solo la última serie de gráficos. Supongo que aquí hay algún enlace, como un puntero de memoria, y este es un problema diferente de lo que se discutió originalmente, pero esta es al menos una razón para elegir algo new sobre Clear() . Sin embargo, tal vez haya una manera de evitarlo.


Clear() eliminará todos los elementos y mantendrá la capacidad existente, mientras que la creación de una nueva lista necesitará al menos una asignación del montón administrado (posiblemente más a medida que se agreguen elementos si la capacidad inicial es pequeña).

  • Si tiene una gran cantidad de artículos y la cantidad de artículos es aproximadamente la misma en cada iteración, usar Clear es potencialmente ligeramente más rápido.

  • Si tiene una cantidad excepcionalmente grande de elementos en una iteración, un número mucho más pequeño en las iteraciones subsiguientes, luego usar Clear es potencialmente más costoso, porque mantendrá en la memoria una lista con una capacidad innecesariamente grande.

Por supuesto, en muchos (¿la mayoría?) Escenarios la diferencia será insignificante.