After reading http://msdn2.microsoft.com/en-us/library/ms972323.aspx and Why String Operations are so Slow, possessed by a deep feeling of duty, I’ve wrote a class that would help developers to handle their string concatenation processes in a smart way.

Why it’s important

Many ASP developers follow good software engineering principles and modularize their code wherever possible. This design normally takes the form of a number of include files that contain functions modeling particular discrete sections of a page. The string outputs from these functions can then be used in various combinations to build a complete page.

Although this is certainly a good design practice, the method used to build the strings that form these discrete HTML code components can have a large bearing on how well the Web site performs and scales – regardless of whether the actual operation is performed from within an ASP include file or a Visual Basic COM component.

A little about string concatenation

String operations are slow in Visual Basic and VBScript. The reason is how they are represented in the memory. Basically they inherit some definitions that are most suited to storing strings whose length never change. Because of this, any operation that changes the length of a string requires that a new block of memory be allocated, and the new content of the string be copied into it. If you are carrying out many consecutive operations that change the length of a string, the operating system must make copies of the string over and over again what cost a lot of time.

Improving the performance

In VB it’s possible to implement faster concatenation using additional variables and steps. This usually makes a heavy use of the mid assign statement which isn’t available in VBScript. But, even without making calls to COM components, it’s possible to do some little tricks to improve the performance.

The most quick and easy solution to mitigate the string concatenations is to use parentheses to change the order of precedence in the expression:

' Instead of writing
dim sText, i
for i = 0 to 200
    sText = sText & _
    "" & vbCrLf & _
        "" & User.id & "" & vbCrLf & _
        "" & User.firstname & "" & vbCrLf & _
        "" & User.lastname & "" & vbCrLf & _
        "" & User.email & "" & vbCrLf & _
    "" & vbCrLf
next
' 
' Use the parenthesized version
dim sText, i
for i = 0 to 200
    sText = sText & (_
    "" & vbCrLf & _
        "" & User.id & "" & vbCrLf & _
        "" & User.firstname & "" & vbCrLf & _
        "" & User.lastname & "" & vbCrLf & _
        "" & User.email & "" & vbCrLf & _
    "" & vbCrLf _
    )
next

This is a very good choice for small (+/- 200) number of iterations.

Another solution available, and this is the one my class is based, is to add the string fragments to the end of a dynamically allocated array, and then join it entries. I’m aware that join does not perform well for arrays containing many strings, but, again, since VBScript does not provide any method to change the string body data without reallocating it and we don’t want to iterate the array with the Response.write ( if you can do it, DO IT! ) to not lose the encapsulation. The join is the least worst method left:

' Instead of writing
dim sText, i
for i = 0 to 5000
    sText = sText & _
    "" & vbCrLf & _
        "" & User.id & "" & vbCrLf & _
        "" & User.firstname & "" & vbCrLf & _
        "" & User.lastname & "" & vbCrLf & _
        "" & User.email & "" & vbCrLf & _
    "" & vbCrLf
next
' 
' Use the StringBuilder version
dim oText, i
set oText = new StringBuilder
for i = 0 to 5000
    oText.append("" & vbCrLf)
    oText.append(    "" & User.id & "" & vbCrLf)
    oText.append(    "" & User.firstname & "" & vbCrLf)
    oText.append(    "" & User.lastname & "" & vbCrLf)
    oText.append(    "" & User.email & "" & vbCrLf)
    oText.append("" & vbCrLf)
next
set oText = nothing

That’s it, if you are interested in the work, visit the goodies section section and look for the download and the docs link.

Additional information

For additional information about improving string handling performance, I suggest taking a careful read in the two articles I mentioned in the brief.