I'm trying to understand why this modified snippet from ExString (quite close to the new string management) remains faster for concatenation.
Do you have an explanation?
Code: Select all
;modified snippet from Exstring to try to be close to the new string management with strings that are now prefixed by their length
;- Use a big cache (#PacketSize) to not ReAllocate the memory at each concat, or #False to Always ReAllocate the memory at each concat with the required Size
#UseCache = #False ;#True/#False
#PacketSize = 4096 ;32
Structure StString
Len.i
*Address
EndStructure
Macro ProcedureReturnIf(Cond, ReturnVal = 0)
If Cond : ProcedureReturn ReturnVal : EndIf
EndMacro
CompilerIf #UseCache
Procedure CheckResizeMemory(*THIS.StString, Length)
Protected *Add, MemSize, Result = #True
MemSize = MemorySize(*THIS\Address)
While Length + (*THIS\Len * SizeOf(Character)) + SizeOf(Character) > MemSize
MemSize + #PacketSize
*Add = ReAllocateMemory(*THIS\Address, MemSize, #PB_Memory_NoClear)
If *Add
If *Add <> *THIS\Address
*THIS\Address = *Add
EndIf
Else
Result = #False
Break
EndIf
Wend
ProcedureReturn Result
EndProcedure
CompilerElse
Procedure ResizeMemory(*THIS.StString, Length)
Protected *Add, Result = #True
*Add = ReAllocateMemory(*THIS\Address, Length + (*THIS\Len * SizeOf(Character)) + SizeOf(Character), #PB_Memory_NoClear)
If *Add
If *Add <> *THIS\Address
*THIS\Address = *Add
EndIf
Else
MessageRequester("ReAllocateMemory Error", "ReAllocateMemory Error" +#CRLF$+ "Help: it is usually a result of a memory corruption at an earlier time in the program by writing at an area outside of the allocated memory area", #PB_MessageRequester_Error)
Result = #False
EndIf
ProcedureReturn Result
EndProcedure
CompilerEndIf
Procedure NewString()
Protected *Buffer, Result
*Buffer = AllocateMemory(1, #PB_Memory_NoClear)
If *Buffer
Protected *THIS.StString
*THIS = AllocateStructure(StString)
*THIS\Address = *Buffer
Result = *THIS
EndIf
ProcedureReturn Result
EndProcedure
Procedure AddString(*THIS.StString, String$)
ProcedureReturnIf(*THIS\Address = 0)
Protected Length = StringByteLength(String$)
ProcedureReturnIf(Length < 1)
Protected Pointer, Result = #True
;ShowMemoryViewer(*THIS\Address, Length + (*THIS\Len * SizeOf(Character)))
CompilerIf #UseCache
Result = CheckResizeMemory(*THIS, Length)
CompilerElse
Result = ResizeMemory(*THIS, Length)
CompilerEndIf
If Result
Pointer = *THIS\Address + (*THIS\Len * SizeOf(Character))
CopyMemoryString(@String$, @Pointer)
*THIS\Len + (Length / SizeOf(Character))
EndIf
ProcedureReturn Result
EndProcedure
Procedure LenString(*THIS.StString)
ProcedureReturnIf(*THIS\Address = 0)
ProcedureReturn *THIS\Len
EndProcedure
Procedure.s GetString(*THIS.StString)
If *THIS\Address = 0 : ProcedureReturn : EndIf
ProcedureReturn PeekS(*THIS\Address, *THIS\Len)
EndProcedure
Procedure.s RightString(*THIS.StString, Len)
If *THIS\Address = 0 Or Len < 1 : ProcedureReturn : EndIf
If Len > *THIS\Len
Len = *THIS\Len
EndIf
ProcedureReturn PeekS(*THIS\Address + ((*THIS\Len - Len) * SizeOf(Character)), Len)
EndProcedure
Procedure FreeString(*THIS.StString)
ProcedureReturnIf(*THIS\Address = 0)
FreeMemory(*THIS\Address)
ClearStructure(*THIS, StString)
EndProcedure
;----------- Main ----------
CompilerIf #PB_Compiler_Debugger
CompilerError "Compile me without Debugger!!!"
CompilerEndIf
a$ = ReplaceString(Space(20), " ", " Hello World!") ; Len=13*20=260 - Final Len=260*2000=520000
OpenConsole("(Ex)String concatenation & right time:")
;- String concatenation time
PrintN("String concatenation & right time:")
Start = ElapsedMilliseconds()
For l = 1 To 2000
b$ = b$ + a$
Next
PrintN(" Final length = " + Str(Len(b$)))
PrintN(" Large concat: "+Str(ElapsedMilliseconds() - Start) + " ms")
Start = ElapsedMilliseconds()
For l = 1 To 500000
c$ = Right(b$, 6)
Next
PrintN(" Right String (" + c$ + "): " +Str(ElapsedMilliseconds() - Start) + " ms")
PrintN("")
;- ExString concatenation time
PrintN("ExString concatenation & right time:")
Start = ElapsedMilliseconds()
ThisString = NewString()
For l = 1 To 2000
AddString(ThisString, a$)
Next
PrintN(" Final length = " + Str(LenString(ThisString)))
PrintN(" Large concat: "+Str(ElapsedMilliseconds() - Start) + " ms")
Start = ElapsedMilliseconds()
For l = 1 To 500000
c$ = RightString(ThisString, 6)
Next
PrintN(" Right String (" + c$ + "): " +Str(ElapsedMilliseconds() - Start) + " ms")
FreeString(ThisString)
PrintN("")
PrintN("Presses the Return key to Close")
Input()String concatenation & right time:
Final length = 520000
Large concat: 31 ms
Right String (World!): 4 ms
ExString concatenation & right time:
Final length = 520000
Large concat: 2 ms
Right String (World!): 4 ms


