Navigation

>> Home
 
ASP.NET (13)
Security (5)
"Classic" ASP (2)
C# (1)
VB.NET (1)
ASP and Flash (1)
 
About Us
 
Chinese Content German Content

 

The ReDim Preserve Performance Trap

Written by: Christoph Wille
Translated by: Bernhard Spuida
First published: 10/25/2000

Whoever works with arrays in VB will be familiar with the ReDim statement for resizing arrays. Today, I will explain in detail why you better shouldn't use this statement in the future, or at least very, very carefully consider its use.

The possible uses of ReDim

Before attacking the ReDim statement and disheveling it, I want to show its most common uses by means of a code sample (redimsamples.aspx). It will show a simple ReDim, as well as a ReDim Preserve:

<% @Page Language="VB" %>
<%
Dim arrStrings(1) as String
Response.Write(UBound(arrStrings) & "<br>")

ReDim arrStrings(20)
Response.Write(UBound(arrStrings) & "<br>")

ReDim Preserve arrStrings(25)
Response.Write(UBound(arrStrings) & "<br>")
%>

ReDim allows increasing as well as decreasing an array's size. For this, a new array is created in each instance. The reason for this is that the VB.NET array is a descendant of the System.Array of the .NET Runtime which by definition has a fixed size on creation. In C# this is obvious, as is demonstrated by the following code emulating ReDim:

string[] arrTest = new string[1];
// and now we want to change the size: ReDim arrTest(20)
arrTest = new string[20];

In itself, this is no problem, the trouble starts with Preserve (today's topic). When using Redim with the Preserve keyword, the old elements are preserved - as copies in the new array.

ReDim Preserve as a Performance Killer

In principle, we already spoiled the whole story - the ReDim Preserve statement creates a new array - and the elements of the old array get copied into the new one. As this happens under VB.NET (as it does under the "old" VB) implicitly, it won't be noticed except for performance loss. To give a somewhat drastic impression of that I set up a loop which redims an array five thousand times (redimloop.aspx).

<% @Page Language="VB" Trace="True" %>
<%
Dim arrStrings() as String
Dim i as Integer

Trace.Write("Redim","Start")

For i = 1 To 5000
  ReDim Preserve arrStrings(i)
  arrStrings(i-1) = i
Next

Trace.Write("Redim","End")
%>

As I switched on tracing, it is easy to obtain performance data:

Of course, this will differ with each call (and with the machine), but at least you get some indication of relative performance.

But what happens in the background when calling ReDim Preserve? To illustrate that, I emulated the ReDim statement in C#, as everything done by ReDim in VB.NET automagically in the background, has to be done explicitly there (redimloopexplicit.aspx).

<% @Page Language="C#" Trace="True" %>
<%
string[] arrStrings = new string[1];
int i;

Trace.Write("Redim","Start");

for (i=1;i<=5000;i++)
{
  string[] arrHelper = new string[i];
  arrStrings.CopyTo(arrHelper, 0);
  arrHelper[i-1] = i.ToString();
  arrStrings = arrHelper;
}

Trace.Write("Redim","End");
%>

Here we can clearly see how bad performance must be - firstly, an array of the new size is created and then the contents of the old array are copied to the new one. The iteration variable is assigned with me performing the cast to String in C# myself. And for finishers, I swap the array variables.

Whoever thinks that VB.NET does something differently is wrong - performance is exactly the same as for ReDim Preserve (my code perhaps is a little better as it doesn't take decreasing the array's size into account). How bad performance actually is can only be realized by comparing it to a superior technology - the ArrayList class.

The Best Solution - ArrayLists

The best solution for a dynamic array is the ArrayList class in the System.Collections namespace. An ArrayList can dynamically grow or shrink, and is very easy to use (arraylistloop.aspx):

<% @Page Language="VB" Trace="True" %>
<% @Import Namespace="System.Collections" %>
<%
Dim arrList as New ArrayList(100)
Dim i as Long

Trace.Write("ArrayList","Start")

For i = 1 To 50000
  arrList.Add(i)
Next

Trace.Write("ArrayList","End")
%>

Those who took a closer look will have noticed that the loop isn't running to five thousand, but to fifty thousand. The reason for that is: with five thousand, performance couldn't be measured. But with fifty thousand, it still is quite impressive:

Execution time is 0.01 to 0.45 - and that with an order of magnitude more loop iterations! I intended to let ReDim Preserve run with this number of iterations as well, but I just reset the server some time during that run...

Conclusion

The lesson to be taken from this article is that under VB.NET ReDim Preserve is something to be positively avoided. When dynamic arrays are needed, it is advisable to use an ArrayList as that basically behaves like a normal array.

Downloading the Code

Click here, to start the download.

©2000-2004 AspHeute.com
All rights reserved. The content of these pages is copyrighted.
All content and images on this site are copyright. Reuse (even parts) needs our written consent.