I was desperately trying to find a faster way of creating an array without one of the items in it, opposed to creating a list of those objects and removing that item.
The reason being is that my array has like 5 items on average, less most times, and creating a list just to remove one item that I no longer wanted in there, seemed way too much to me.
Since I coded my own profiler a while back, I decided to put that method, and another one I thought of, under a test, and heck are the results significant.
int[] a1 = new int[] { 1, 2, 3 };
Method 1 (creating a list of the objects and removing the 2nd item):
Profiler.Start("Method 1");
List<int> a2 = new List<int>(a1);
a2.RemoveAt(1);
Profiler.Stop("Method 1");
Method 2 (creating an array of the same size but one, and discluding the 2nd item):
Profiler.Start("Method 2");
int[] a3 = new int[a1.Length - 1];
int l = 0;
for (int i = 0; i < a1.Length; i++) if (a1[i] != 2) { a3[l] = a1[i]; l++; }
Profiler.Stop("Method 2");
Profiler results:
https://i.sstatic.net/al8i6.png
The question Why is the difference in performance so significant?
I never actually took the time to study the differences between an array and a list.
It seems that the overhead is coming from the initialisation for the contents of the list rather than from the call to List.RemoveAt()
.
In other words, the line List<int> a2 = new List<int>(a1);
is dominating the time.
Here's some code that attempts to eliminate the time taken for List.RemoveAt()
and Array.Copy()
.
The results from a release build on my PC are:
LIST Elapsed: 00:00:00.4724841
ARRAY Elapsed: 00:00:00.4670488
LIST Elapsed: 00:00:00.4714016
ARRAY Elapsed: 00:00:00.4675552
LIST Elapsed: 00:00:00.4703538
ARRAY Elapsed: 00:00:00.4698310
which shows the times to be fairly similar.
The test program is:
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace Demo
{
public static class Program
{
public static void Main()
{
int[] a1 = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
int trials = 3;
int iterations = 10000000;
Stopwatch sw = new Stopwatch();
for (int i = 0; i < trials; ++i)
{
for (int j = 0; j < iterations; ++j)
{
List<int> a2 = new List<int>(a1);
sw.Start();
a2.RemoveAt(1);
sw.Stop();
}
Console.WriteLine("LIST Elapsed: " + sw.Elapsed);
sw.Reset();
for (int j = 0; j < iterations; ++j)
{
int[] a3 = new int[a1.Length - 1];
int l = 0;
sw.Start();
for (int k = 0; k < a1.Length; k++)
{
if (a1[k] != 2)
{
a3[l] = a1[k];
l++;
}
}
sw.Stop();
}
Console.WriteLine("ARRAY Elapsed: " + sw.Elapsed);
sw.Reset();
}
}
}
}