Qual é mais rápido: limpar a coleção ou instanciar novos

Eu tenho algumas listas genéricas no meu código, que possuem dezenas ou centenas de elementos. Às vezes, preciso preencher essas listas com outros objects, então a pergunta é: o que será mais rápido, chamar o método Clear() ou criar uma new List() ?

o que será mais rápido, chamar o método Clear() ou criar uma `nova lista ()?

Isso é impossível de responder. Isso realmente depende de muitos fatores, incluindo quanto tempo a coleção existe.

A melhor opção aqui seria:

  1. Faça o perfil do aplicativo e veja se isso realmente importa. Provavelmente não fará qualquer diferença perceptível, nesse caso, eu usaria o método que faz mais sentido em termos de como você pensa sobre esse object.

  2. Se isso importa, escreva os dois conjuntos de código e meça a diferença de velocidade (se houver).

De uma perspectiva prática, chamar Clear() não reduzirá a memory (usada pelo próprio List ), pois não reduz a capacidade da lista, apenas elimina os valores contidos nela. Criar uma nova List fará com que uma nova lista seja alocada, o que, por sua vez, causará mais alocações com o crescimento.

Isso, no entanto, não significa que será mais lento – em muitos casos, a realocação será mais rápida, pois é menos provável que você promova os grandes arrays em gerações de garbage collection maiores, o que, por sua vez, pode manter o processo de GC muito mais rápido.

Sem conhecer seu cenário exato e medir em um criador de perfil, não há como saber qual é o melhor em seu cenário.

Eu executei este teste:

 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 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 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 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 Clear(List list) { list.Clear(); return list; } private static List Reinitialize(List list) => new List(); private static List ReinitializeAndCollect(List list) { list = new List(); GC.Collect(); GC.WaitForPendingFinalizers(); return list; } 

Minha conclusão com base nos resultados do meu processador Core i3 comum:

No caso de milhares de elementos – é melhor limpar a lista. É rápido e eficiente em termos de memory.

Se a coleção tiver mais de 100 000 elementos, a reboot torna-se mais atraente. Se, após o perfil, você achar que há um gargalo aqui, use-o. A reboot será muito rápida, mas, como mostra o terceiro teste de método, a garbage collection no futuro será tão lenta quanto a simples limpeza da lista.

Portanto, a resposta curta é: se você não criou o perfil do seu aplicativo, use Clear . Reutilizar objects é bom. Se você fez – você já sabe o que fazer.

Isso dependerá de muitos fatores e, a longo prazo, provavelmente não importará (o suficiente para contar) em seu programa.

Do msdn docs .Clear() é uma operação O (n).

Inicializando uma nova instância terá sua própria sobrecarga, bem como (se você manter a coleção o mesmo comprimento, uma operação O (n): ou seja, n chamadas Add() ).

Realmente, a única maneira de testar isso é configurar alguns cronômetros no seu programa e ver qual é o efeito se você realmente acha que vale a pena. Com toda a probabilidade; não vale a pena.

Meus pensamentos seriam que se você já criou uma coleção, Clear() , é por isso que existe um método Clear() em primeiro lugar.

Embora isso possa ser frustrante, a resposta é realmente que não deveria importar. A diferença de tempo entre os dois será tão pequena que provavelmente não fará diferença para o seu aplicativo. Faça o que leva a um código mais claro e compreensível e tente não programar para micro-otimizações.

Clear() removerá todos os elementos e manterá a capacidade existente, enquanto a criação de uma nova Lista precisará de pelo menos uma alocação do heap gerenciado (possivelmente mais, à medida que os itens forem adicionados se a capacidade inicial for pequena).

  • Se você tiver um grande número de itens e o número de itens for aproximadamente o mesmo em cada iteração, o uso de Clear é potencialmente um pouco mais rápido.

  • Se você tiver um número excepcionalmente grande de itens em uma iteração, então um número muito menor em iterações subseqüentes, usar Clear é potencialmente mais caro, porque você estará mantendo na memory uma lista com uma capacidade desnecessariamente grande.

Naturalmente, em muitos cenários (a maioria), a diferença será insignificante.

Talvez eu esteja fazendo algo fundamentalmente errado aqui, mas enquanto desenvolvo um aplicativo ASP.NET em C # estou encontrando uma grande diferença ao usar Clear () vs. new. Estou criando uma página de statistics com charts, que possuem séries de dados. Para cada gráfico eu tenho uma seção onde eu faço isso:

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

então outro gráfico segue.

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

Isso funciona muito bem com a series sendo realocada com o new , mas quando eu faço

 series.Clear(); 

em vez disso, chart.Series a input dentro de chart.Series e chartistLineCharts para que a página de statistics acabe recuperando apenas a série do último gráfico. Eu suponho que há algum link, como um ponteiro de memory, aqui e isso é um problema diferente do que é originalmente discutido, mas isso é pelo menos uma razão para escolher o new sobre Clear() . Talvez haja uma maneira de evitar isso.

Eu fiz vários testes para mim. Resultados (velocidade) são:

  • para listas pequenas – por exemplo, 3 itens, é mais rápido criar novas listas, mas a diferença não é grande
  • para 10 ou mais itens, em média, é melhor limpar as listas. Para tipos de valor muito melhor (por exemplo, 3-4 vezes), para tempos de valor como 20% melhor.

Mas, no final, é melhor criar um perfil de aplicativo e encontrar gargalos para todo o aplicativo.

Se seus objects forem de valor, eu usaria Clear () para reduzir as alocações futuras de memory. Caso contrário, ambas as abordagens são quase idênticas.