Hi all,
I tested it with own StringBuilder functions:
Code:
; Speed test of string concatenation
; and the use of StringBuilder functions
Structure StringBuilder
pString.l
StringSize.l
MemSize.l
BlockSize.l
InitDone.l
EndStructure
Procedure StringBuilder_Info()
Static sbInfo.StringBuilder
ProcedureReturn @sbInfo
EndProcedure
Procedure StringBuilder_Init(BlockSize)
Protected *sbInfo.StringBuilder
*sbInfo = StringBuilder_Info()
If *sbInfo\InitDone : FreeMemory(*sbInfo\pString) : EndIf
; BlockSize min. 1024 ($400) Byte
If BlockSize < $400 : BlockSize = $400 : EndIf
; BlockSize max. 1 MByte ($100000) Byte
If BlockSize > $100000 : BlockSize = $100000 : EndIf
If BlockSize <> (BlockSize & $FC00):
BlockSize = (BlockSize & $FC00) + 1024
EndIf
*sbInfo\BlockSize = BlockSize
*sbInfo\StringSize = 0
*sbInfo\pString = AllocateMemory(BlockSize)
If *sbInfo\pString <> 0
*sbInfo\InitDone = #True
*sbInfo\MemSize = *sbInfo\BlockSize
Else
*sbInfo\InitDone = #False
*sbInfo\MemSize = 0
EndIf
ProcedureReturn *sbInfo\InitDone
EndProcedure
Procedure StringBuilder_Clear()
Protected *sbInfo.StringBuilder
*sbInfo=StringBuilder_Info()
If *sbInfo\InitDone
FreeMemory(*sbInfo\pString)
*sbInfo\pString = 0
*sbInfo\StringSize = 0
*sbInfo\BlockSize = 0
*sbInfo\InitDone = #False
*sbInfo\MemSize = 0
EndIf
EndProcedure
Procedure StringBuilder_Add(pAddString.l)
Protected *sbInfo.StringBuilder
Protected StrLen
Protected pNewString, NewMemSize, NewStringSize
*sbInfo = StringBuilder_Info()
StrLen = MemoryStringLength(pAddString)
NewStringSize = StrLen + *sbInfo\StringSize
If NewStringSize + 1 > *sbInfo\MemSize
NewMemSize = *sbInfo\MemSize+*sbInfo\BlockSize
pNewString=AllocateMemory(NewMemSize)
If pNewString = 0 : ProcedureReturn #False : EndIf
CopyMemory(*sbInfo\pString,pNewString,*sbInfo\StringSize)
FreeMemory(*sbInfo\pString)
*sbInfo\pString=pNewString
*sbInfo\MemSize=NewMemSize
EndIf
CopyMemory(pAddString,*sbInfo\pString+*sbInfo\StringSize,StrLen)
*sbInfo\StringSize = NewStringSize
EndProcedure
Procedure.s StringBuilder_GetString()
Protected *sbInfo.StringBuilder
Protected WholeString.s
*sbInfo=StringBuilder_Info()
WholeString = PeekS(*sbInfo\pString)
ProcedureReturn WholeString
EndProcedure
#TestLoop=1024*64
t=GetTickCount_()
For i = 1 To #TestLoop
s1.s+"+"
Next
time1=GetTickCount_()-t
MessageRequester("StringTest", "StringFunctions: " + Str(time1) + " ms")
t=GetTickCount_()
If StringBuilder_Init(2048)
sAdd.s="+"
For i = 1 To #TestLoop
StringBuilder_Add(@sAdd)
Next
s2.s = StringBuilder_GetString()
StringBuilder_Clear()
time2=GetTickCount_()-t
MessageRequester("StringTest", "StringFunctions: " + Str(time1) + " ms" + #CRLF$ + "StringBuilder: " + Str(time2) + " ms")
If CompareMemoryString(s1,s2,0) <> 0
MessageRequester("StringTest", "Strings sind nicht identisch!")
Else
MessageRequester("StringTest", "Strings sind identisch!")
EndIf
Else
MessageRequester("StringTest", "StringBuilder konnte nicht initialisiert werden!")
EndIf
Test: 64.000 times the character "+" is added to a string. with normal PB-String functions it takes about 11s at my PC. With the StringBuilder functions it takes 16ms.
So if you have to concatenate much strings, it makes sense to use own concatenation functions:
ATTENTION: The above functions are written only for testing. It is not possible to handel two or more strings at the same time, because there is only ONE string buffer. It would be possible to rewrite the functions to use more stringbuffers. AND the above functions does not handel the string limitations of PureBasic ... so the StringBuilder_GetString() could fail if the concatenated string is too big (at the moment a PB-String can have a maximum of 70508 characters ... tested with PB 3.91).
cu, helpy