Which is faster: clear collection or instantiate new

.NetPerformanceListOptimizationCollections

.Net Problem Overview


I have some number of generic lists in my code, that have tens or hundreds elements. Sometimes I need to refill this lists with other objects, so question is: what will be faster, to call Clear() method or creating a new List<T>()?

.Net Solutions


Solution 1 - .Net

> what will be faster, to call Clear() method or creating a `new List()?

This is impossible to answer. It really depends on a lot of factors, including how long the collection has existed.

The best option here would be to:

  1. Profile the application, and see if this really matters. It likely won't make any perceptible difference, in which case, I'd use the method that makes the most sense in terms of how you think of this object.

  2. If it does matter, write both sets of code, and measure the difference in speed (if any).

From a practical perspective, calling Clear() will not actually reduce the memory (used by the List<T> itself), as it doesn't shrink the list's capacity, only eliminates the values contained within it. Creating a new List<T> will cause a new list to be allocated, which will in turn cause more allocations with growth.

This, however, does not mean that it will be slower - in many cases, reallocating will be faster as you're less likely to promote the large arrays into higher garbage collection generations, which in turn can keep the GC process much faster.

Without knowing your exact scenario and measuring in a profiler, there is no way to know which is better in your scenario.

Solution 2 - .Net

I've run this test:

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;
}

My conclusion based on a results of my ordinary core i3 processor:

In case of thousands of elements - it is better to clear list. It is fast and memory efficient.

If collection has more than 100 000 elements - reinitializing becomes more attractive. If after profiling you think that there is a bottleneck here, use it. Re-initialization will be very fast, but as third method test shows, future garbage collecting will be about as slow as just clearing the list.

So short answer is: if you didn't profiled your application, use Clear. Reusing objects is good. If you did - you already know what to do.

Solution 3 - .Net

This is going to depend on a lot of factors, and in the long run, it probably will not matter (enough to count) in your program.

From the msdn docs .Clear() is a O(n) operation.

Initializing a new instance will have its own overhead as well as (if you keep the collection the same length, a O(n) operation: i.e. n Add() calls).

Really the only way to test this is to set up some stopwatches in your program and see what the effect is if you really think it is worth it. In all likelihood; it's not worth it.

My thoughts would be that if you've already created a collection, Clear() it, that's why there is a Clear() method in the first place.

Solution 4 - .Net

While this may be frustrating, the answer really is that it shouldn't matter. The time difference between the two is going to be so small that it probably won't make any difference to your application. Do what leads to cleaner, more understandable code, and try not to program for micro-optimizations.

Solution 5 - .Net

Clear() will remove all elements, and maintain the existing capacity, whereas creating a new List will need at least one allocation from the managed heap (possibly more as items are added if the initial capacity is small).

  • If you have a large number of items, and the number of items is roughly the same on each iteration, then using Clear is potentially slightly faster.

  • If you have an exceptionally large number of items on one iteration, then a much smaller number on subsequent iterations, then using Clear is potentially more costly, because you'll be keeping in memory a list with an unnecessarily large capacity.

Of course, in many (most?) scenarios the difference will be negligible.

Solution 6 - .Net

Maybe I'm doing something fundamentally wrong here but while developing an ASP.NET application in C# I'm encountering quite a difference when using Clear() vs. new. I'm creating a statistics page with charts, which have data series. For each chart I have a section where I do this:

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

then another chart follows.

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);

This works just fine with series being reallocated with new, but when I do

series.Clear();

instead I actually clear the entry inside chart.Series and chartistLineCharts so the statistics page ends up retrieving only the last chart's series. I assume there is some link, like a memory pointer, here and this is a different issue than what is originally discussed, but this is at least a reason to pick new over Clear(). Perhaps there is a way to avoid it though.

Solution 7 - .Net

I've made several tests for myself. Results (speed) are:

  • for small lists - eg 3 items, its faster to create new lists, but the difference is not big
  • for 10 or more items on average it is better to clear lists. For value types much better (eg 3-4 times), for value times like 20% better.

But in the end, it's better to profile application and find bottlenecks for whole application.

Solution 8 - .Net

If your objects are value types I'd use Clear() to reduce memory future allocations. Otherwise both approaches are almost identical.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMrimshView Question on Stackoverflow
Solution 1 - .NetReed CopseyView Answer on Stackoverflow
Solution 2 - .NetastefView Answer on Stackoverflow
Solution 3 - .NetNominSimView Answer on Stackoverflow
Solution 4 - .NetChris ShainView Answer on Stackoverflow
Solution 5 - .NetJoeView Answer on Stackoverflow
Solution 6 - .NethugView Answer on Stackoverflow
Solution 7 - .NetMichal DobrodenkaView Answer on Stackoverflow
Solution 8 - .NetalexmView Answer on Stackoverflow