StringBuilder Class for VB

Speed up string operations by up to 100 times or more using this class

StringBuilder Test Project

If you need to build a string by adding lots of pieces together, VB's string handling is slow because a new string is created in memory every time a new piece is added. This article presents a class which allocates a string chunk and then uses memory copy methods to manipulate the data within the same string's memory. The result is a string class which can perform orders of magnitude quicker than the equivalent VB code.

Improving String Handling Performance in VB

VB's strings are fundamentally based on the COM BSTR object. As is the case with strings in most current programming languages, BSTRs are fixed in size once they are created. If you want to change the length of a string in any way once it has been created, for example, by adding another string to it, behind the scenes a new string with the correct length is created, the data copied into it and then the previous string is discarded. To a VB programmer, this is transparent, since you still refer to the string using the same variable name, however, this is clearly not memory efficient if you want to append a large number of strings together.

To improve matters, you can trade off increased memory allocation for performance by allocating a larger string than you need to start with, storing the actual length you are using and then manipulating the memory that is pointed to by the string. This is the method used by the class presented with this article.

Accessing String Memory

To access the memory pointed to by a string, you can use VB's StrPtr function. This returns a pointer to the buffer allocated for the string. Remember that in the COM BSTR used by VB is a Unicode string, and therefore there are two bytes for each character in the buffer. You can then copy and move bytes using the ubiquitous Win32 RtlMoveMemory API call (which is typically aliased to CopyMemory when used in VB since that's what Bruce McKinney did when he first describing it in "Hardcore Visual Basic").

The StringBuilder Class

The StringBuilder class provided with the download provides a convenient class which uses the techniques described above to allow you to append, insert, remove and find characters within a single string. When you are performing a large number of string operations, for example, appending 10,000 strings together, you can easily see a 100x increase in performance.

StringBuilder Class Properties and Methods

  • Length (Get)
    Returns the length of the string (note this is not the same as the size of the string the class internally stores, which is returned by the Capacity property the object).
  • ToString (Get)
    Returns the string.
  • TheString (Set)
    Sets the string to the specified string.
  • Append
    Appends the specified string. The string is passed ByRef for performance (no copy is made).
  • AppendByVal
    Appends the specified string by value. Use this when you want to append a non-string argument.
  • Insert
    Inserts a string at the specified (1-based) index. The string is passed ByRef for performance (no copy is made).
  • InsertByVal
    Appends the specified string by value. Use this when you want to insert a non-string argument.
  • Remove
    Removes lLen characters from the specifed (1-based) index.
  • Find
    Finds the specified string using VB's InStr method on the internal buffer.

There are also a few properties and methods for tuning the memory usage of the class:

  • Capacity (Get)
    Returns the current capacity of the StringBuilder class.
  • HeapMinimise
    Reduces the internal string size to the smallest possible multiple of ChunkSize given its current length
  • ChunkSize (Get, Set)
    Gets/sets the size of the chunk which is appended to the internal string whenever more capacity is needed. The default is 8192 characters, or 16k. When a StringBuilder object is instantiated, no initial string capacity is allocated. Hence if memory is a concern the ChunkSize can be set much lower prior to using the class.

The following code demonstrates how you might use the class to create a simple HTML document:

Private Function CreateHtml( _
    ByVal sTitle As String, _
    lstDocuments As ListBox _
    ) As String

Dim i As Long
Dim buf As New cStringBuilder
   
   buf.Append("<HTML><HEAD><TITLE>")
   buf.Append(sTitle)
   buf.Append("</TITLE></HEAD><BODY>")

   buf.Append("<H1>")
   buf.Append(sTitle)
   buf.Append("</H1>")

   buf.Append("<TABLE><TR><TD>Document Id</TD><TD>Name</TD></TR>")   

   For i = 0 to lstDocuments.ListCount - 1
     buf.Append("<TR><TD>")
     buf.AppendByVal(lstDocuments.ItemData(i))
     buf.Append("</TD><TD>")
     buf.Append(lstDocuments.List(i))
     buf.Append("</TD></TR>")
   Next i      

   buf.Append("</TABLE></BODY></HTML>")   

   CreateHtml = buf.ToString
End Function