home · blog · groups · about us · contact us
DevelopmentNow Blog
 Wednesday, October 25, 2006
 
 

Ok so this is one of my favorite tips in .NET. Of course, there are a lot of things I like about the framework, but anyhow...

A lot of times you'll want to create an array of items, but you don't know how big the array is going to be. You're hoping you can declare an array & just dynamically add items to it like you can with an ArrayList. The first impulse might be to do something like

string[] foo = new string[] { };
foo[1] = "some text";
foo[2] = "some text";

But, that won't work -- you'll get an System.IndexOutOfBoundsException.

However, in .NET 1.1, your friend the ArrayList comes to the rescue with this fun stuff:

ArrayList fooArrayList = new ArrayList();
fooArrayList.Add("some text");
fooArrayList.Add("some more text");

string[] foo = (string[])fooArrayList.ToArray(typeof(string));

Yay! Now you can dynamically add stuff to an array. But wait, there's more -- with .NET 2.0, the Array class somes with a new Resize() generic method, so you can also do this:

string[] foo3 = new string[]{};

// resize array & add an item
Array.Resize<string>(ref foo3, foo3.Length + 1);
foo3[foo3.Length - 1] = "some text";

// resize array & add an item
Array.Resize<string>(ref foo3, foo3.Length + 1);
foo3[foo3.Length - 1] = "some text";

So that's cool. But which is faster, you ask? Let's see, here's the code we used to add 10,000 items to an array.

const int MAX_ITEMS = 100000;
DateTime start;
TimeSpan timeTaken;

// time ArrayList
start = DateTime.Now;
ArrayList fooArrayList = new ArrayList();
for (int i = 0; i < MAX_ITEMS; i++)
{
fooArrayList.Add("some text");
}
string[] foo2 = (string[])fooArrayList.ToArray(typeof(string));
timeTaken = DateTime.Now.Subtract(start);
Console.WriteLine("ArrayList\t" + timeTaken.Milliseconds + " msec\n\n");

// time Array.Resize
start = DateTime.Now;
string[] foo3 = new string[] { };
for (int i = 0; i < MAX_ITEMS; i++)
{
Array.Resize<string>(ref foo3, foo3.Length + 1);
foo3[foo3.Length - 1] = "some text";
}
timeTaken = DateTime.Now.Subtract(start);
Console.WriteLine("Resize\t" + timeTaken.Milliseconds + " msec\n\n");

// prompt for ENTER
Console.WriteLine("Press ENTER.");
Console.ReadLine();

Final result: ArrayList 0 msec, Array.Resize 250 msec. If we go for 100,000 items, it ends up being ArrayList 10 msec, Array.Resize 45000 msec. ;(

So, that's not surprising. The ArrayList probably only resizes things when it needs to and keeps a buffer. So what if we change Array.Resize to resize the Array in chunks of, say, 10,000? And let's go for 1,000,000 items in the array.

const int MAX_ITEMS = 1000000;
DateTime start;
TimeSpan timeTaken;

// time ArrayList
start = DateTime.Now;
ArrayList fooArrayList = new ArrayList();
for (int i = 0; i < MAX_ITEMS; i++)
{
fooArrayList.Add("some text");
}
string[] foo2 = (string[])fooArrayList.ToArray(typeof(string));
timeTaken = DateTime.Now.Subtract(start);
Console.WriteLine("ArrayList\t" + timeTaken.Milliseconds + " msec\n\n");

// time Array.Resize
start = DateTime.Now;
string[] foo3 = new string[] { };
int itemCount = 0;
int arrayChunkSize = 10000;
for (int i = 0; i < MAX_ITEMS; i++)
{
// only resize the array if we need to, and do it in chunks
if (foo3.Length <= itemCount)
Array.Resize<string>(ref foo3, itemCount + arrayChunkSize);
foo3[itemCount] = "some text";
itemCount++;
}
// trim the final size of the array
Array.Resize<string>(ref foo3, itemCount);
timeTaken = DateTime.Now.Subtract(start);
Console.WriteLine("Resize\t" + timeTaken.Milliseconds + " msec\n\n");

// prompt for ENTER
Console.WriteLine("Press ENTER.");
Console.ReadLine();

Much better. ArrayList 150 msec, Array.Resize (chunked) 700 msec. But, ArrayList is still faster. So I guess ArrayList is pretty efficient about expanding its buffer when you add items to it, which is a good thing, since I like ArrayLists.

So...there's your tip, plus we looked at a new Array generic method, and did a bit of performance analysis. If you need a dynamically-sized array, just use an ArrayList and cast it to an array using the .ToArray function. Remember, you can do this for any array, even an array of custom objects.

October 25, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [2]

Related posts:
SubSonic DAL layers in Visual Studio
Intro to BDD
Easy FTP Uploads in your EXEs
FireBug 1.0.1 is out
WYSIWYG editor in minutes
jQuery for javascript effects


« Document your Databases for Free | Main | Subversion in Visual Studio .NET -- Ankh... »