UFO ET IT

더 빠릅니다 : 컬렉션을 지우거나 새로 인스턴스화

ufoet 2020. 12. 4. 21:31
반응형

더 빠릅니다 : 컬렉션을 지우거나 새로 인스턴스화


내 코드에는 수십 또는 수백 개의 요소가있는 일반 목록이 몇 개 있습니다. 때로는이 목록을 다른 개체로 다시 채워야하므로 질문은 Clear()메서드 를 호출 하거나 생성하는 것이 더 빠를 것입니다 new List<T>().


Clear()메서드 를 호출 하거나`new List ()를 만드는 것이 더 빠를 것입니다 .

대답하기 불가능합니다. 컬렉션이 얼마나 오랫동안 존재했는지 등 많은 요인에 따라 달라집니다.

여기에서 가장 좋은 옵션은 다음과 같습니다.

  1. 애플리케이션을 프로파일 링하고 이것이 정말로 중요한지 확인하십시오. 눈에 띄는 차이를 만들지 않을 것입니다.이 경우이 물체를 어떻게 생각하는지에 대해 가장 합리적인 방법을 사용하겠습니다.

  2. 중요한 경우 두 코드 세트를 모두 작성하고 속도 차이를 측정하십시오 (있는 경우).

실용적인 관점에서, 호출 Clear()List<T>목록의 용량을 줄이지 않고 그 안에 포함 된 값만 제거하기 때문에 실제로 메모리 ( 자체가 사용하는)를 줄이지 않습니다. List<T>새 목록을 만들면 새 목록이 할당되고, 그 결과 증가에 따라 더 많은 할당이 발생합니다.

그러나 이것이 더 느리다는 것을 의미하지는 않습니다. 많은 경우에 재 할당이 더 빨라질 것입니다 . 대형 어레이를 더 높은 가비지 콜렉션 세대로 승격시켜 GC 프로세스를 훨씬 빠르게 유지할 가능성이 적기 때문입니다.

정확한 시나리오를 모르고 프로파일 러에서 측정 하지 않으면 시나리오 에서 어느 것이 더 나은지 알 방법이 없습니다.


이 테스트를 실행했습니다.

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.


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.


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.


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.


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.


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.


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

참고URL : https://stackoverflow.com/questions/10901020/which-is-faster-clear-collection-or-instantiate-new

반응형