Which is faster: clear collection or instantiate new

后端 未结 8 870
遇见更好的自我
遇见更好的自我 2020-12-01 06:26

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 f

相关标签:
8条回答
  • 2020-12-01 06:26

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

    0 讨论(0)
  • 2020-12-01 06:28

    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.

    0 讨论(0)
  • 2020-12-01 06:29

    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.

    0 讨论(0)
  • 2020-12-01 06:39

    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.

    0 讨论(0)
  • 2020-12-01 06:44

    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.

    0 讨论(0)
  • 2020-12-01 06:46

    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.

    0 讨论(0)
提交回复
热议问题