ASP String concatenation

I have read several articles (for example, www.adopenstatic.com/experiments/stringconcatenation.asp) where the inefficiency of string concatentation is discussed.

I have lots of code that builds a web page with a long sequence of string concatenations, such as the following:

strHTML = ""
strHTML = strHTML & strHTMLcode1
strHTML = strHTML & strHTMLcode2
strHTML = strHTML & strHTMLcode3
strHTML = strHTML & strHTMLcode4
strHTML = strHTML & strHTMLcode5
strHTML = strHTML & strHTMLcode6

and so on, where "strHTMLcodeX" is some actual HTML. These concatenations often go on for between 50 or 100 lines (maybe more).

The code is not necessarily needed right away, so simple replacement with Response.Write calls would not often be the best approach.

My first inclincation would simply to replace the above with the following:

strHTML = strHTMLcode1  & strHTMLcode2 & strHTMLcode3 & strHTMLcode4  & strHTMLcode5 & strHTMLcode6

However, this seems kind of ugly, especially with 100 variables and literals.

Can anyone recommend a nicer approach?
jasimon9Asked:
Who is Participating?
 
ajitanandCommented:
Hello,

String concatenating is VBScript is too slow. Rather use this FastString Class:
------------------------------
<%
Class FastString
      Dim stringArray, growthRate, numItems

      Private Sub Class_Initialize()
            growthRate = 50: numItems = 0
            ReDim stringArray(growthRate)
      End Sub

      Public Sub Append(ByVal strValue)
            ' next line prevents type mismatch error if strValue is null. Performance hit is negligible.
            strValue=strValue & ""
            If numItems > UBound(stringArray) Then ReDim Preserve stringArray(UBound(stringArray) + growthRate)
            stringArray(numItems) = strValue:numItems = numItems + 1
      End Sub

      Public Sub Reset
            Erase stringArray
            Class_Initialize
      End Sub
      
      Public Function concat()
            Redim Preserve stringArray(numItems)
            concat = Join(stringArray, "")
      End Function
End Class
%>
-----------------------------------

To use it you just need to call as following:
<%
'Call the following once...
Dim ofast
Set oFast = New FastString

'Do this whenever you want...
oFast.Reset
oFast.Append "This is a substring1!"
oFast.Append "This is a substring2!"
oFast.Append "This is a substring3!"

Response.Write oFast.Concat

'Start again!
oFast.Reset
oFast.Append "This is a substring4!"
oFast.Append "This is a substring5!"
oFast.Append "This is a substring6!"

oFast.Reset
Response.Write oFast.Concat

Set oFast = Nothing
%>

----------------------------------------

This code gives you a HUGE performance benefit.

Hope this helps.

warm regards,
Ajit Anand
0
 
appariCommented:
it seems you are generating complete HTML code in asp and using response.write

if that is the case instead of using response.write, even for static HTML, keep static HTML as it is and use ASP code to generate only the dynamic part of the page.
0
 
ap_sajithCommented:
An easy way round is..

strHTML = strHTML &_
            strHTMLcode1  &_
            strHTMLcode2 &_
            strHTMLcode3 &_
            strHTMLcode4 & _
            strHTMLcode5 &_
            strHTMLcode6

The reason why this is less strenuous because the strHTML variable doesnt have to be reassigned each time. The main reason for string concatenations spiking up the CPU usage is the memory reallocation required each tim you reassign a variable. This method also improves readability... even for 100 lines :)

There is a much more efficient and neater method using a string concatenation calss.

http://www.15seconds.com/howto/pg000929.htm

The class is really efficient and works wonders with the CPU usage :)

Hope this helps..

Cheers!!
0
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

 
jasimon9Author Commented:
To appari: of course you are correct, when the HTML is statis. The whole point of building the HTML in ASP is because it is dynamic. I did not specifically say so, assuming that it would be obvious.
0
 
jasimon9Author Commented:
To ap_sajith: your first suggestion provides a way to make the code more readable, but otherwise is the same as the alternative I proposed. A slight improvement.

I will check out your second suggestion at 15seconds.com.
0
 
jasimon9Author Commented:
Looking at the StringBuilder class: has anyone done any performance comparisons against simply

strHTML = strHTMLcode0 &_
          strHTMLcode1  &_
          strHTMLcode2 &_
          strHTMLcode3 &_
          strHTMLcode4 & _
          strHTMLcode5 &_

...
          strHTMLcodeX

where the "X" is a pretty large number?
0
 
jasimon9Author Commented:
I have tested the StringBuillder suggested by ap_sajith (from http://www.15seconds.com/howto/pg000929.htm) and
FastString suggested by ajitanand. Both are extremely similar, with some additional error checking in FastString to prevent errors if the string argument is NULL.

My first tests showed StringBuilder with a slight but consistent speed advantage. However, passing a NULL string did cause it to crash. By adding the one line of code from FastString to StringBuilder (strValue=strValue & ""), the crashing is prevented and both algorithms run about the same speed.

Normally, I would give points to the first responder when answers are essentially identical. However, because of the slight superiority of FastString due to the error checking, I am going to split the points. I guess if you could always be assured that no NULLs would occur then you could omit the error checking. However, I believe this would not be good practice.

Here is a typical timing output  for 10000 iterations with the corrected StringBuilder (string output omitted):

Plain Concatentation: 5.265625
******
Using FastString: 0.1992188
******
Using StringBuilder: 0.203125

As you can see, either algorithm (when corrected for NULL) is acceptable and a big improvement over plain concatentation. Even greater gains observered with 20000 iterations.

Incidentally, for a small number of iterations, plain concatenation is almost as fast. For 1000 iterations, here are the timings:

Plain Concatentation: 0.046875
******
Using FastString: 0.015625
******
Using StringBuilder: 0.015625

Here is the code used to run the test. YMMV.

<%
' Use this class to concatenate strings in a much more
' efficient manner than simply concatenating a string
' (strVariable = strVariable & "your new string")
Class StringBuilder
      Dim arr       'the array of strings to concatenate
      Dim growthRate  'the rate at which the array grows
      Dim itemCount   'the number of items in the array

      Private Sub Class_Initialize()
            growthRate = 50
            itemCount = 0
            ReDim arr(growthRate)
      End Sub

      'Append a new string to the end of the array. If the
      'number of items in the array is larger than the
      'actual capacity of the array, then "grow" the array
      'by ReDimming it.
      Public Sub Append(ByVal strValue)
        strValue=strValue & ""  'code borrowed from FastString to prevent crash on NULL'
            If itemCount > UBound(arr) Then
                  ReDim Preserve arr(UBound(arr) + growthRate)
            End If

            arr(itemCount) = strValue
            itemCount = itemCount + 1
      End Sub

      'Concatenate the strings by simply joining your array
      'of strings and adding no separator between elements.
      Public Function ToString()
            ToString = Join(arr, "")
      End Function
End Class

Class FastString
     Dim stringArray, growthRate, numItems

     Private Sub Class_Initialize()
          growthRate = 50: numItems = 0
          ReDim stringArray(growthRate)
     End Sub

     Public Sub Append(ByVal strValue)
          ' next line prevents type mismatch error if strValue is null. Performance hit is negligible.
          strValue=strValue & ""
          If numItems > UBound(stringArray) Then ReDim Preserve stringArray(UBound(stringArray) + growthRate)
          stringArray(numItems) = strValue:numItems = numItems + 1
     End Sub

     Public Sub Reset
          Erase stringArray
          Class_Initialize
     End Sub

     Public Function concat()
          Redim Preserve stringArray(numItems)
          concat = Join(stringArray, "")
     End Function
End Class

Dim iTime1, iTime2, iX, iLimit
iLimit = 10000

'plain concatentation'
dim strVar
iTime1 = Timer
strVar = "<br>"
for iX = 1 to iLimit
      strVar = strVar & "this is Plain1|"
next
iTime2 = Timer
Response.Write("<br>Plain Concatentation: " & iTime2 - iTime1)
Response.Write(strVar)

'using FastString'
Dim ofast
Set oFast = New FastString
iTime1 = Timer
oFast.Reset
oFast.Append "<br>"
oFast.Append NULL
For iX = 0 To iLimit
      oFast.Append("this is Fancy2")
Next
iTime2 = Timer
Response.Write("<br>******")
Response.Write("<br>Using FastString: " & iTime2 - iTime1)
Response.Write oFast.Concat
Set oFast = Nothing

'using StringBuilder'
Dim objBuilder
Set objBuilder = new StringBuilder
iTime1 = Timer
objBuilder.Append("<br>")
objBuilder.Append(NULL)
For iX = 0 To iLimit
      objBuilder.Append("this is Fancy1")
Next
iTime2 = Timer
Response.Write("<br>******")
Response.Write("<br>Using StringBuilder: " & iTime2 - iTime1)
Response.Write objBuilder.ToString()
Set objBuilder = nothing

%>
0
 
ap_sajithCommented:
@Jasimon, Thank you for posting back the results of your testings. I know the faststring class from the following article in eggheadcafe.com. I did not post it because of the obvious reason that it is similar to the stringbuilder class.
http://www.eggheadcafe.com/articles/20011227.asp

The article even has a link that lets you test the performance.

>>To ap_sajith: your first suggestion provides a way to make the code more readable, but otherwise is the same as the alternative I proposed. A slight improvement.<<

Well, I had overlooked your comment (strHTML = strHTMLcode1  & strHTMLcode2 & strHTMLcode3 & strHTMLcode4  & strHTMLcode5 & strHTMLcode6).

As for the points, i am not here for the points any more.....well... atleast for now ;o)....Dont really have the time to spare.

Once again, thanks for posting the excellent feedback.

Cheers!!
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.