Performance differences with different methods for initializing lists and populations

I tried to find out if setting the list throughput in the constructor can smooth out the already insignificant performance differences between using List<T>(IEnumerable<T>)vs List<T>()+ AddRange(IEnumerable<T>).

I found that setting the capacity before AddRange()actually leads to about the same performance of building a list with the original collection.

But there is more. What if you use Add()instead AddRange()? For some reason, performance improves by 32% .

So what if I use Add()without initializing a list constructor with initial capacity? It seems that the performance is worse than the previous Add () approach, but still better than that AddRange(): a 26% increase in performance.

It is rather strange for me to wonder if my test was valid; therefore, I am sending the tests that I have done (it runs in release mode without a debugger).

Can anyone confirm this?

int items = 100000;
int cycles = 10000;

var collectionToCopy = Enumerable.Range( 0, items );

var sw0 = new Stopwatch();
sw0.Start();
for( int i = 0; i < cycles; i++ )
{
    List<int> list = new List<int>( collectionToCopy );
}
sw0.Stop();
Console.WriteLine( sw0.ElapsedMilliseconds );

var sw1 = new Stopwatch();
sw1.Start();
for( int i = 0; i < cycles; i++ )
{
    List<int> list = new List<int>( items );
    list.AddRange( collectionToCopy );
}
sw1.Stop();
Console.WriteLine( sw1.ElapsedMilliseconds );

var sw4 = new Stopwatch();
sw4.Start();
for( int i = 0; i < cycles; i++ )
{
    List<int> list = new List<int>();
    list.AddRange( collectionToCopy );
}
sw4.Stop();
Console.WriteLine( sw4.ElapsedMilliseconds );

var sw2 = new Stopwatch();
sw2.Start();
for( int i = 0; i < cycles; i++ )
{
    List<int> list = new List<int>( items );
    foreach( var item in collectionToCopy )
        list.Add( item );
}
sw2.Stop();
Console.WriteLine( sw2.ElapsedMilliseconds );

var sw3 = new Stopwatch();
sw3.Start();
for( int i = 0; i < cycles; i++ )
{
    List<int> list = new List<int>();
    foreach( var item in collectionToCopy )
        list.Add( item );
}
sw3.Stop();
Console.WriteLine( sw3.ElapsedMilliseconds );

Results:

13400 - constructor initialized by collection

13423 - constructor initialized with capacity + AddRange (collection)

14857 - parameterless constructor + AddRange (collection)

9003 - constructor initialized by capacity + Add (element)

9841 - constructor without parameters + Add (element)

+4
1

Enumerable.Range(0, items). Enumerable.Range(0, items).ToList(); .

AddRange(IEnumerable collectionToCopy) . (, , ,...), . ().

using(IEnumerator<T> en = collection.GetEnumerator()) {
   while(en.MoveNext()) {
        Insert(index++, en.Current);                                    

, List.AddRange, , IEnumertor

+4

Source: https://habr.com/ru/post/1673025/


All Articles