Home > Articles > Programming > Visual Basic

  • Print
  • + Share This
Like this article? We recommend

A Faster Approach

One solution to this dilemma is to unlink the memory reallocation from the string-concatenation operation, allowing the developer to implement a more efficient algorithm. This solution has been implemented in an in-process VB COM component (ConCat.dll) that encapsulates string storage and the required concatenation functionality. The source code for this VB 6.0 class is presented in Listing 1.

Listing 1: Source Code for the ConCat Class

' =================================================== '
' CConCat:                      '
' This class provides an alternative, more efficient '
' approach to string concatenation. Concatenation of '
' large VB strings requires reallocation of memory at '
' each concatenation. The approach used here reduces '
' the number of memory reallocations.         '
'                           '
' Empirical results indicate that this is faster than '
' standard VB concatenation for strings greater than '
' 1K in length, with the level of improvement growing '
' with the size of the string.            '
'                           '
'  Public Property Get Text() as String       '
'  Public Property Let Text(ByVal sNew as String)  '
'  Public Property Get Increment() as Long      '
'  Public Property Let Increment(ByVal nNew as Long) '
'  Public Property Get Length() as Long       '
'  Public Sub Cat(ByVal sNewPart as String)     '
'                           '
' Copyright © 2001 by Scott R. Loban.         ' ===================================================== '

Private m_sText As String   '-- Text being stored in object
Private m_nPointer As Long  '-- Pointer to end of string
Private m_nIncrement As Long '-- Number of bytes to add at a time

'--- Return the Text Stored in the Class ---'
Public Property Get Text() As String
 Dim ErNum, ErDesc, ErSrc
On Error GoTo ErrHandler
 Text = Left$(m_sText, m_nPointer)
Exit Property
ErrHandler:
 ErNum = Err.Number
 ErDesc = Err.Description
 ErSrc = Err.Source & ", CConCat.Text"
 Err.Raise ErNum, ErSrc, ErDesc
End Property

'--- Set (replace) the Text Stored in the Class ---'
Public Property Let Text(ByVal new_sText As String)
 Dim ErNum, ErDesc, ErSrc
On Error GoTo ErrHandler
 m_sText = new_sText
 m_nPointer = Len(m_sText)
Exit Property
ErrHandler:
 ErNum = Err.Number
 ErDesc = Err.Description
 ErSrc = Err.Source & ", CConCat.Text"
 Err.Raise ErNum, ErSrc, ErDesc
End Property

'--- Return the Current Reallocation Increment ---'
Public Property Get Increment() As Long
 Dim ErNum, ErDesc, ErSrc
On Error GoTo ErrHandler
 Increment = m_nIncrement
Exit Property
ErrHandler:
 ErNum = Err.Number
 ErDesc = Err.Description
 ErSrc = Err.Source & ", CConCat.Increment"
 Err.Raise ErNum, ErSrc, ErDesc
End Property

'--- Set a New Reallocation Increment ---'
Public Property Let Increment(ByVal new_nIncrement As Long)
 Dim ErNum, ErDesc, ErSrc
On Error GoTo ErrHandler
 If new_nIncrement > 0 Then
  m_nIncrement = new_nIncrement
 End If
Exit Property
ErrHandler:
 ErNum = Err.Number
 ErDesc = Err.Description
 ErSrc = Err.Source & ", CConCat.Increment"
 Err.Raise ErNum, ErSrc, ErDesc
End Property

'--- Return the Length of the Text Stored in the Class ---'
Public Property Get Length() As Long
 Dim ErNum, ErDesc, ErSrc
On Error GoTo ErrHandler
 Length = m_nPointer
Exit Property
ErrHandler:
 ErNum = Err.Number
 ErDesc = Err.Description
 ErSrc = Err.Source & ", CConCat.Length"
 Err.Raise ErNum, ErSrc, ErDesc
End Property

'--- Concatenate the Text Stored in the Class and a Passed String ---'
Public Sub Cat(ByVal sNewPart As String)
 Dim nLen As Long
 Dim ErNum, ErDesc, ErSrc

On Error GoTo ErrHandler
 
 nLen = Len(sNewPart)
 
 If (m_nPointer + nLen) >= Len(m_sText) Then  '-- Not enough room
  If nLen > m_nIncrement Then         '-- Need nLen more bytes
   m_sText = m_sText & Space$(nLen)     '-- Do Reallocation
  Else                    '-- Add more space
   m_sText = m_sText & Space$(m_nIncrement) '-- Do Reallocation
  End If
 End If
 
 '--- Store the NewPart in the String ---'
 Mid$(m_sText, m_nPointer + 1, nLen) = sNewPart
 
 '--- Adjust the Pointer ---'
 m_nPointer = m_nPointer + nLen
Exit Sub
ErrHandler:
 ErNum = Err.Number
 ErDesc = Err.Description
 ErSrc = Err.Source & ", CConCat.Cat"
 Err.Raise ErNum, ErSrc, ErDesc
End Sub

Private Sub Class_Initialize()
 Dim ErNum, ErDesc, ErSrc
On Error GoTo ErrHandler
 m_nIncrement = 50000
 m_sText = ""
 m_nPointer = 0
Exit Sub
ErrHandler:
 ErNum = Err.Number
 ErDesc = Err.Description
 ErSrc = Err.Source & ", CConCat.Class_Initialize"
 Err.Raise ErNum, ErSrc, ErDesc
End Sub

ConCat works by preallocating a larger initial block of memory for the text being stored and then making memory reallocations explicit—and, therefore, controllable. A public method (Cat) is used to concatenate a specified string to the existing text by using the VB Mid$ function to write the string into the text storage. The component maintains an index that acts as a pointer to the end of the string being stored. The Cat method also determines when reallocation is necessary and how much additional memory to allocate. A set of public properties provides access to the text and its length.

Table 1 illustrates the results of empirical testing to compare the performance of Append and the ConCat class. As the table indicates, the approach implemented in ConCat can provide performance that is much faster.

Table 1 Comparison of Append and ConCat Performance

Test Case

Append (&)

ConCat

1000 x 10 characters

0*

0*

2000 x 10 characters

2

0*

4000 x 10 characters

8

0*

8000 x 10 characters

35

0*

16,000 x 10 characters

151

0*

32,000 x 10 characters

619

0*

64,000 x 10 characters

 

1

128,000 x 10 characters

 

1

256,000 x 10 characters

 

3


Although the concatenation operator built into Visual Basic 6.0 is great for most tasks, this alternative approach offers significant improvement for the special case of concatenating many small strings into a large string, such as when dynamically generating HTML or XML text streams.

  • + Share This
  • 🔖 Save To Your Account