Fast string

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Fast string

Post by Mijikai »

+ 1
highend
Enthusiast
Enthusiast
Posts: 123
Joined: Tue Jun 17, 2014 4:49 pm

Re: Fast string

Post by highend »

+ 1
User avatar
Kukulkan
Addict
Addict
Posts: 1352
Joined: Mon Jun 06, 2005 2:35 pm
Location: germany
Contact:

Re: Fast string

Post by Kukulkan »

I know that I'm somehow "old fashioned", but I think it is upon the developer to understand, at least in a basic form, how strings are working. And if I find such a scenario, I do it like this since 30 years now:

Code: Select all

DisableDebugger

Str.s
Dummy.s
#Text = "1234567890"

Time = ElapsedMilliseconds()

For i=1 To 100000
  Dummy + #Text
  If Len(Dummy) > 2048
    Str + Dummy
    Dummy = ""
  EndIf
Next i
Str + Dummy

MessageRequester("", StrF((ElapsedMilliseconds()-Time)/1000, 3))
While the initial function in the first thread takes me 48 seconds to complete, the 6 additional lines enhanced the speed to be 0.38 seconds. This is simple to use and really helpful. I do it like this all the time when I concatenate lager strings.

It is definitely not the fastest way possible, but solved it for me cross platform and reliable.

Kukulkan
HanPBF
Enthusiast
Enthusiast
Posts: 562
Joined: Fri Feb 19, 2010 3:42 am

Re: Fast string

Post by HanPBF »

Thanks for that example.

I like solutions where things are easy and fast and not only "fastest as possible even hard to implement".

What speed factors do we talk about?
- naive string handling
- Kukulkans less memory mappings method
- fast string builder
(It's about huge strings, isn't it?)

And... I can not see the problem.
Shouldn't it be possible in any situation (CSV, etc.) to guess the max size of the string and use Space() and PokeS?
Another shrink is then one fast memory operation.
Cyllceaux
Enthusiast
Enthusiast
Posts: 458
Joined: Mon Jun 23, 2014 1:18 pm
Contact:

Re: Fast string

Post by Cyllceaux »

Just a little fun code, to remember this is still a thing :D

Code: Select all

EnableExplicit

Procedure StringAppend(*sb,string.s)
	Protected size,*Offset
	If *sb
		size=MemorySize(*sb)
		*Offset=size
	EndIf
	size+StringByteLength(string)
	*sb=ReAllocateMemory(*sb,size,#PB_Memory_NoClear)
	PokeS(*sb+*offset,string,-1,#PB_String_NoZero)
	ProcedureReturn *sb
EndProcedure

Procedure.s SBToString(*sb)
	ProcedureReturn PeekS(*sb,MemorySize(*sb)/SizeOf(Character))
EndProcedure

OpenConsole()

Define i
Define s.s="Lalala"
Define *sb=StringAppend(*sb,"Lalala")
#max=100000


Define start=ElapsedMilliseconds()
For i=1 To #max
	s+"La"
Next
Define ende=ElapsedMilliseconds()

PrintN(Str(ende-start)+" - "+Len(s))

start=ElapsedMilliseconds()
For i=1 To #max
	*sb=StringAppend(*sb,"La")
Next
ende=ElapsedMilliseconds()

PrintN(Str(ende-start)+" - "+Len(SBToString(*sb)))

Input()
CloseConsole()
Result

Code: Select all

40733 - 200006
23 - 200006
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: Fast string

Post by Dude »

Cyllceaux wrote:Just a little fun code, to remember this is still a thing :D
I have an issue with extremely slow strings, that I posted about here:

http://www.purebasic.fr/english/viewtop ... 13&t=70568

I'd love to see strings being fast natively, to avoid POKES and memory buffers and mucking around like that.
Shield wrote:This is not generally a PureBasic "problem"
Technically, no. But if we can write long blocks of code as a "workaround", then such workarounds need to become native.
User avatar
marcoagpinto
Addict
Addict
Posts: 939
Joined: Sun Mar 10, 2013 3:01 pm
Location: Portugal
Contact:

Re: Fast string

Post by marcoagpinto »

+1
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: Fast string

Post by Dude »

To build a 505 KB string, it's literally faster to use a ListIconGadget and a disk write/read, than to build it the traditional way :!: :shock: :|

Code: Select all

Debug "Please wait, speed testing..."

DisableDebugger

OpenWindow(0,200,200,200,100,"test",#PB_Window_Invisible)
ListIconGadget(0,10,10,180,80,"test",180)

; Prep the ListIconGadget with 505 KB of text:

items=5000
For a=1 To items
  AddGadgetItem(0,-1,Str(a)+Space(100))
Next

; Build a 505 KB string directly from the gadget:

start.q=ElapsedMilliseconds()
For a=1 To items
  one$+GetGadgetItemText(0,a)
Next
one.q=ElapsedMilliseconds()-start

; Build another 505 KB string using disk access:

start.q=ElapsedMilliseconds()
f$=GetTemporaryDirectory()+"string-speed-test"
If CreateFile(0,f$)
  For a=1 To items
    WriteString(0,GetGadgetItemText(0,a))
  Next
  CloseFile(0)
  If ReadFile(0,f$)
    two$=ReadString(0,#PB_File_IgnoreEOL)
    CloseFile(0)
  EndIf
  DeleteFile(f$)
EndIf
two.q=ElapsedMilliseconds()-start

; The results:

EnableDebugger

Debug "Len(one$)="+Str(Len(one$))+" and took "+Str(one)+" ms" ; 8216 ms (8 seconds!)
Debug "Len(two$)="+Str(Len(two$))+" and took "+Str(two)+" ms" ; 22 ms (not even a quarter of a second!)
User avatar
Josh
Addict
Addict
Posts: 1183
Joined: Sat Feb 13, 2010 3:45 pm

Re: Fast string

Post by Josh »

Dude wrote:22 ms (not even a quarter of a second!)
:mrgreen:
sorry for my bad english
User avatar
the.weavster
Addict
Addict
Posts: 1536
Joined: Thu Jul 03, 2003 6:53 pm
Location: England

Re: Fast string

Post by the.weavster »

Dude's test made me wonder how fast it would be to add strings you want to concatenate to a list and then iterate over that list and copy each item into a memory block and then PeekS() at the outcome.

I've finessed that idea slightly and here's the result:

Code: Select all

DisableDebugger

Structure StringBuilderItem
  item.s
  size.i
EndStructure

Structure StringBuilder
  size.i
  count.i
  List item.StringBuilderItem()
EndStructure

Procedure StringBuilder_Add(*sb.StringBuilder,itm$)
  nSize = StringByteLength(itm$)
  *sb\size = *sb\size + nSize
  *sb\count = *sb\count + 1
  AddElement(*sb\item())
  *sb\item()\item = itm$
  *sb\item()\size = nSize
EndProcedure

Procedure StringBuilder_Clear(*sb.StringBuilder)
  ClearList(*sb\item())
  *sb\count = 0
  *sb\size = 0
EndProcedure

Procedure StringBuilder_Free(*sb.StringBuilder)
  ClearList(*sb\item())
  FreeStructure(*sb)
EndProcedure

Procedure.s StringBuilder_Get(*sb.StringBuilder,idx.i)
  If idx > *sb\count - 1
    ProcedureReturn ""
  EndIf
  SelectElement(*sb\item(),idx)
  ProcedureReturn *sb\item()\item
EndProcedure

Procedure.s StringBuilder_GetChunk(*source,nSize)
  *bfr = AllocateMemory(nSize + 4)
  CopyMemory(*source,*bfr,nSize)
  out$ = PeekS(*bfr)
  FreeMemory(*bfr)
  ProcedureReturn out$
EndProcedure

Procedure.i StringBuilder_GetLongest(*sb.StringBuilder)
  nLongest = 0
  ResetList(*sb\item())
  While NextElement(*sb\item())
    If *sb\item()\size > nLongest
      nLongest = *sb\item()\size
    EndIf
  Wend
  ProcedureReturn nLongest
EndProcedure

Procedure StringBuilder_Insert(*sb.StringBuilder,idx,val$)
  If idx > *sb\count - 1 : ProcedureReturn : EndIf
  SelectElement(*sb\item(),idx)
  InsertElement(*sb\item())
  nSize = StringByteLength(val$)
  *sb\count = *sb\count + 1
  *sb\size = *sb\size + nSize
  *sb\item()\item = val$
  *sb\item()\size = nSize
EndProcedure

Procedure.s StringBuilder_Join(*sb.StringBuilder,delim$="")
  nSizeDelim = StringByteLength(delim$)
  nAdder = ListSize(*sb\item()) * nSizeDelim
  *bfr = AllocateMemory(*sb\size + nAdder + 4)
  nLoops = 0
  ResetList(*sb\item())
  While NextElement(*sb\item())
    PokeS(*bfr+nPos,*sb\item()\item,*sb\item()\size)
    nPos = nPos + *sb\item()\size
    nLoops = nLoops + 1
    If nSizeDelim > 0 And nLoops < *sb\count
      PokeS(*bfr+nPos,delim$,nSizeDelim)
      nPos = nPos + nSizeDelim
    EndIf
  Wend
  out$ = PeekS(*bfr,*sb\size)
  FreeMemory(*bfr)
  ProcedureReturn out$
EndProcedure

Procedure.i StringBuilder_New()
  *s.StringBuilder = AllocateStructure(StringBuilder)
  *s\count = 0
  *s\size = 0
  ProcedureReturn *s
EndProcedure

Procedure StringBuilder_Remove(*sb.StringBuilder,idx.i)
  If idx > *sb\count - 1 : ProcedureReturn : EndIf
  SelectElement(*sb\item(),idx)
  *sb\count = *sb\count - 1
  *sb\size = *sb\size - *sb\item()\size
  DeleteElement(*sb\item())
EndProcedure

Procedure StringBuilder_Replace(*sb.StringBuilder,idx.i,val$)
  If idx > *sb\count - 1 : ProcedureReturn : EndIf
  SelectElement(*sb\item(),idx)
  *sb\size = *sb\size - *sb\item()\size
  nSize = StringByteLength(val$)
  *sb\size = *sb\size + nSize
  *sb\item()\item = val$
  *sb\item()\size = nSize
EndProcedure

Procedure.i StringBuilder_Split(val$,delim$)
  *sb = StringBuilder_New()
  nSizeDel = StringByteLength(delim$)
  nSizeVal = StringByteLength(val$)
  If nSizeDel = 0 Or nSizeVal = 0
    ProcedureReturn *sb
  EndIf
  nEnd = 0 : nLen = 0 : nStart = 0
  While nEnd <= nSizeVal
    If CompareMemory(@val$+nEnd,@delim$,nSizeDel)
      StringBuilder_Add(*sb,StringBuilder_GetChunk(@val$+nStart,nLen))
      nEnd = nEnd + nSizeDel
      nStart = nEnd
      nLen = 0
    Else
      nEnd = nEnd + 1
      nLen = nLen + 1
    EndIf
  Wend
  If nLen > 0
    StringBuilder_Add(*sb,StringBuilder_GetChunk(@val$+nStart,nLen))
  EndIf
  ProcedureReturn *sb
EndProcedure

items=5000
joinstart.q=ElapsedMilliseconds()
*s.StringBuilder = StringBuilder_New()
For a=1 To items
  StringBuilder_Add(*s,Str(a)+Space(100))
Next
s$=StringBuilder_Join(*s,"|")
joinend.q=ElapsedMilliseconds()-joinstart

splitstart.q=ElapsedMilliseconds()
*s1.StringBuilder = StringBuilder_Split(s$,"|")
splitend.q=ElapsedMilliseconds()-splitstart

EnableDebugger

Debug "Join: Len(s$)= "+Str(Len(s$))+" and took "+Str(joinend)+" ms"
Debug "Split: Elements(s$)= "+Str(*s1\count)+" and took "+Str(splitend)+" ms"

StringBuilder_Free(*s)
StringBuilder_Free(*s1)

s$ = "Probably the best sparkling wine in the world"
*s.StringBuilder = StringBuilder_Split(s$," ")
StringBuilder_Replace(*s,3,"malt")
StringBuilder_Remove(*s,4)
StringBuilder_Insert(*s,4,"vinegar")
Debug StringBuilder_Join(*s," ")
Copying Dude's test (but with a delimiter so I can split the string again) I get:
Join 8ms
Split 31ms

Edit: Tweaked to add procedures to insert, remove, replace and get longest in order to handle this.
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: Fast string

Post by Dude »

@Kukulkan: your code below is magic! I have no idea how it works, but it lets me build a 386 KB string (a list of 9895 filenames in a folder, with 40 characters per name) in just 390 ms! Thank you! :)

So, what's with the 2048 size test? Can you explain how that works? When I halved it to 1024, the routine was slower; and when I doubled it to 4096, my app crashed with an illegal memory access error. So 2048 seems to be the sweet-spot.

Code: Select all

For i=1 To 100000
  Dummy + #Text
  If Len(Dummy) > 2048
    Str + Dummy
    Dummy = ""
  EndIf
Next i
Str + Dummy
DontTalkToMe
Enthusiast
Enthusiast
Posts: 334
Joined: Mon Feb 04, 2013 5:28 pm

Re: Fast string

Post by DontTalkToMe »

Yes, stringbuilders in PB and strings prepended with the actual length would be useful language additions.
So ...
forumuser
User
User
Posts: 98
Joined: Wed Apr 18, 2018 8:24 am

Re: Fast string

Post by forumuser »

@Cyllceaux

Code: Select all

Procedure StringAppend(*sb,string.s)
   Protected size,*Offset
   If *sb
      size=MemorySize(*sb)
      *Offset=size
   EndIf
   size+StringByteLength(string)
   *sb=ReAllocateMemory(*sb,size,#PB_Memory_NoClear)
   PokeS(*sb+*offset,string,-1,#PB_String_NoZero)
   ProcedureReturn *sb
EndProcedure

Procedure.s SBToString(*sb)
   ProcedureReturn PeekS(*sb,MemorySize(*sb)/SizeOf(Character))
EndProcedure
When I want to use your procedures in a loop but build different strings on each iteration,
how do I "reset" it?

Code: Select all

FreeMemory(*sb)
after each iteration won't work...
ShadowStorm
Enthusiast
Enthusiast
Posts: 237
Joined: Tue Feb 14, 2017 12:07 pm

Re: Fast string

Post by ShadowStorm »

Code: Select all

Structure MyStringBuilder
  
  *MyStringBuilderMemoryiD
  MyStringBuilderSize.q
  MyStringBuilderRemaining.q
  MyStringBuilderPosition.q
  
EndStructure

Global Dim MyStringBuilder.MyStringBuilder(0)

Procedure.b initialiseStringBuilder(Taille.q)
  
  If Taille.q <= 0
    Taille.q = 1
  EndIf
  
  If ArraySize(MyStringBuilder(), 1) = -1
    ProcedureReturn 0
  EndIf
  
  If MyStringBuilder.MyStringBuilder(0)\MyStringBuilderMemoryiD = 0
    
    *MyStringBuilderMemoryiD = AllocateMemory(StringByteLength(Space(Taille.q), #PB_Unicode) + 2)
    
    If *MyStringBuilderMemoryiD
      
      MyStringBuilder.MyStringBuilder(0)\MyStringBuilderMemoryiD = *MyStringBuilderMemoryiD
      MemorySize.q = MemorySize(MyStringBuilder.MyStringBuilder(0)\MyStringBuilderMemoryiD) / 2
      MemorySize.q - 1
      
      MyStringBuilder.MyStringBuilder(0)\MyStringBuilderRemaining = MemorySize.q
      MyStringBuilder.MyStringBuilder(0)\MyStringBuilderSize = MemorySize.q
      MyStringBuilder.MyStringBuilder(0)\MyStringBuilderPosition = 0
      
      ProcedureReturn 1
      
    Else
      ProcedureReturn 0
      
    EndIf
    
  Else
    ProcedureReturn 0
    
  EndIf
  
EndProcedure
Procedure.b isStringBuilder(ElementiD.i)
  
  ArraySize.i = ArraySize(MyStringBuilder(), 1)
  
  If ArraySize.i = -1 Or ElementiD.i < 0 Or ElementiD.i > ArraySize.i
    ProcedureReturn 0
  EndIf
  
  If MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD <> 0
    ProcedureReturn  1
    
  Else
    ProcedureReturn 0
    
  EndIf
  
EndProcedure
Procedure.b StringBuilderAddElement(Taille.q)
  
  ArraySize.i = ArraySize(MyStringBuilder(), 1)
  
  If ArraySize.i = -1
    ProcedureReturn 0
  EndIf
  
  ReDim MyStringBuilder.MyStringBuilder(ArraySize.i + 1)
  
  *MyStringBuilderMemoryiD = AllocateMemory(StringByteLength(Space(Taille.q), #PB_Unicode) + 2)
  
  If *MyStringBuilderMemoryiD
    
    MyStringBuilder.MyStringBuilder(ArraySize.i + 1)\MyStringBuilderMemoryiD = *MyStringBuilderMemoryiD
    MemorySize.q = MemorySize(MyStringBuilder.MyStringBuilder(ArraySize.i + 1)\MyStringBuilderMemoryiD) / 2
    MemorySize.q - 1
    
    MyStringBuilder.MyStringBuilder(ArraySize.i + 1)\MyStringBuilderRemaining = MemorySize.q
    MyStringBuilder.MyStringBuilder(ArraySize.i + 1)\MyStringBuilderSize = MemorySize.q
    MyStringBuilder.MyStringBuilder(ArraySize.i + 1)\MyStringBuilderPosition = 0
    
    ProcedureReturn 1
    
  Else
    ProcedureReturn 0
    
  EndIf
  
  ProcedureReturn ElementiD.i + 1
  
EndProcedure
Procedure.b StringBuilderClearString(ElementiD.i)
  
  If Not isStringBuilder(ElementiD.i)
    ProcedureReturn 0
  EndIf
  
  MemorySize.q = MemorySize(MyStringBuilder.MyStringBuilder(ArraySize.i + 1)\MyStringBuilderMemoryiD) / 2
  MemorySize.q - 1
  
  FillMemory(MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD, MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderSize, #Null , #PB_Unicode)
  
  MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderRemaining = MemorySize.q
  MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderSize = MemorySize.q
  MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderPosition = 0
  
  ProcedureReturn 1
  
EndProcedure
Procedure.b StringBuilderReAllocate(ElementiD.i, Taille.q)
  
  If Taille.q <= 0
    Taille.q = 1
  EndIf
  
  If Not isStringBuilder(ElementiD.i)
    ProcedureReturn 0
  EndIf
  
  *MyStringBuilderMemoryiD = ReAllocateMemory(MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD, Taille.q)
  
  If *MyStringBuilderMemoryiD
    
    MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD = *MyStringBuilderMemoryiD
    MemorySize.q = MemorySize(MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD) / 2
    MemorySize.q - 1
    
    TailleActuel.q = MemorySize.q
    NouvelleTaille.q = Taille.q
    Restant.q = MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderRemaining
    
    If TailleActuel.q > NouvelleTaille.q
      
      Difference.q = TailleActuel.q - NouvelleTaille.q
      Restant.q - Difference.q
      
      If Restant.q < 0
        MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderPosition + Restant.q
        Restant.q = 0
      EndIf
      
      MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderRemaining = Restant.q
      MyStringBuilder.MyStringBuilder(ArraySize.i + 1)\MyStringBuilderSize = Taille.q
      
    ElseIf NouvelleTaille.q > TailleActuel.q
      
      Difference.q = NouvelleTaille.q - TailleActuel.q
      Restant.q + Difference.q
      
      MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderRemaining  = Restant.q
      MyStringBuilder.MyStringBuilder(ArraySize.i + 1)\MyStringBuilderSize = Taille.q
      
    EndIf
    
    ProcedureReturn 1
    
  Else
    ProcedureReturn 0
    
  EndIf
  
EndProcedure
Procedure.b StringBuilderAddString(ElementiD.i, String.s)
  
  If Not String.s > ""
    ProcedureReturn 0
  EndIf
  
  If isStringBuilder(ElementiD.i)
    
    If Len(String.s) > MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderRemaining
      
      *MyStringBuilderMemoryiD = ReAllocateMemory(MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD, MemorySize(MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD) + (StringByteLength(String.s) * 10))
      
      If *MyStringBuilderMemoryiD
        
        MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD = *MyStringBuilderMemoryiD
        
        MemorySize.q = MemorySize(MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD) / 2
        MemorySize.q - 1
        
        If PokeS(MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD + (MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderPosition * 2), String.s, -1, #PB_Unicode)
          
          MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderRemaining = MemorySize.q - MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderPosition - Len(String.s)
          MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderSize = MemorySize.q
          MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderPosition + Len(String.s)
          
          ProcedureReturn 1
          
        Else
          ProcedureReturn 0
          
        EndIf
        
      Else
        ProcedureReturn 0
        
      EndIf
      
    Else
      
      MemorySize.q = MemorySize(MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD) / 2
      MemorySize.q - 1
      
      If PokeS(MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD + (MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderPosition * 2), String.s, -1, #PB_Unicode)
        
        MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderRemaining = MemorySize.q - MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderPosition - Len(String.s)
        MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderSize = MemorySize.q
        MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderPosition + Len(String.s)
        
        ProcedureReturn 1
        
      Else
        ProcedureReturn 0
        
      EndIf
      
    EndIf
    
  Else
    ProcedureReturn 0
    
  EndIf
  
EndProcedure
Procedure.S StringBuilderGetString(ElementiD.i)
  
  If isStringBuilder(ElementiD.i)
    ProcedureReturn PeekS(MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD, -1, #PB_Unicode)
    
  Else
    ProcedureReturn ""
    
  EndIf
  
EndProcedure
Procedure.i StringBuilderGetMemoryiD(ElementiD.i)
  
  If isStringBuilder(ElementiD.i)
    ProcedureReturn MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderMemoryiD
    
  Else
    ProcedureReturn 0
    
  EndIf
  
EndProcedure
Procedure.i StringBuilderGetMemorySize(ElementiD.i)
  
  If isStringBuilder(ElementiD.i)
    ProcedureReturn MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderSize
    
  Else
    ProcedureReturn 0
    
  EndIf
  
EndProcedure
Procedure.i StringBuilderGetMemoryRemaining(ElementiD.i)
  
  If isStringBuilder(ElementiD.i)
    ProcedureReturn MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderRemaining
    
  Else
    ProcedureReturn 0
    
  EndIf
  
EndProcedure
Procedure.i StringBuilderGetMemoryPosition(ElementiD.i)
  
  If isStringBuilder(ElementiD.i)
    ProcedureReturn MyStringBuilder.MyStringBuilder(ElementiD.i)\MyStringBuilderPosition
    
  Else
    ProcedureReturn 0
    
  EndIf
  
EndProcedure
; 
; Procedure.i StringBuilderDeletteElement()
;   
;   
;   
; EndProcedure
; 
; Procedure.i StringBuilderCopyElement()
;   
;   
;   
; EndProcedure

Abc$ = "Abcdefghijklmnopqrstuvwxyz"

If initialiseStringBuilder(0)
  
  For MonStringBuilder1.i = 0 To 5
    
    If isStringBuilder(MonStringBuilder1.i)
      
      MessageRequester("StringBuilder initialisation...", "StringBuilderID = " + Str(MonStringBuilder1.i) + Chr(13) + Chr(10) +
                                                          "StringBuilder MemoryiD = " + Str(StringBuilderGetMemoryiD(MonStringBuilder1.i)) + Chr(13) + Chr(10) +
                                                          "StringBuilder Memory Size = " + Str(StringBuilderGetMemorySize(MonStringBuilder1.i)) + Chr(13) + Chr(10) +
                                                          "StringBuilder Memory Remaining = " + Str(StringBuilderGetMemoryRemaining(MonStringBuilder1.i)) + Chr(13) + Chr(10) +
                                                          "StringBuilder Memory Position = " + Str(StringBuilderGetMemoryPosition(MonStringBuilder1.i)))
      
      Time1 = ElapsedMilliseconds()
      
      For i = 1 To 255
        
        Write.b = StringBuilderAddString(MonStringBuilder1.i, Abc$)
        MemoryiD.q = StringBuilderGetMemoryiD(MonStringBuilder1.i)
        MemorySize.q = StringBuilderGetMemorySize(MonStringBuilder1.i)
        MemoryRemaining.q = StringBuilderGetMemoryRemaining(MonStringBuilder1.i)
        MemoryPosition.q = StringBuilderGetMemoryPosition(MonStringBuilder1.i)
        ;     
        ;     Debug "MemoryiD: " + Str(MemoryiD.q)
        ;     Debug "MemorySize: " + Str(MemorySize.q)
        ;     Debug "MemoryRemaining: " + Str(MemoryRemaining.q)
        ;     Debug "MemoryPosition: " + Str(MemoryPosition.q)
        ;     Debug "Write: " + Str(Write.b)
        ;     Debug "---------------------------"
        ;     
      Next
      
      Time2 = ElapsedMilliseconds()
      
      MessageRequester("StringBuilder Résultat...", "StringBuilderID = " + Str(MonStringBuilder1.i) + Chr(13) + Chr(10) +
                                                    "StringBuilder MemoryiD = " + Str(StringBuilderGetMemoryiD(MonStringBuilder1.i)) + Chr(13) + Chr(10) +
                                                    "StringBuilder Memory Size = " + Str(StringBuilderGetMemorySize(MonStringBuilder1.i)) + Chr(13) + Chr(10) +
                                                    "StringBuilder Memory Remaining = " + Str(StringBuilderGetMemoryRemaining(MonStringBuilder1.i)) + Chr(13) + Chr(10) +
                                                    "StringBuilder Memory Position = " + Str(StringBuilderGetMemoryPosition(MonStringBuilder1.i)) + Chr(13) + Chr(10) +
                                                    "Time Elapsed = " + Str(Time2 - Time1) + " Ms.")
      
      If StringBuilderAddElement(1)
        
      Else
        Debug 0
        
      EndIf
      
    Else
      MessageRequester("StringBuilder Résultat...", "Erreur, Le StringBuilder n°" + Str(MonStringBuilder1.i) + ", n'a pas put être initialisé !", 16)
      
    EndIf
    
  Next
  
Else
  MessageRequester("StringBuilder Résultat...", "Erreur, Le StringBuilder n'a pas put être initialisé !", 16)
  
EndIf


For i = 0 To 5
  Debug StringBuilderGetString(I)
  Debug "----------"
Next

I am French, I do not speak English.
My apologies for the mistakes.

I have sometimes problems of expression
I am sometimes quite clumsy, please excuse me and let me know.
ShadowStorm
Enthusiast
Enthusiast
Posts: 237
Joined: Tue Feb 14, 2017 12:07 pm

Re: Fast string

Post by ShadowStorm »

Code: Select all

Structure StructureMyStringBuilder
  
  *MyStringBuilderMemoryID
  MyStringBuilderSize.q
  MyStringBuilderRemaining.q
  MyStringBuilderPosition.q
  
EndStructure

Global NewMap MapMyStringBuilder.StructureMyStringBuilder()

; Crée un nouveau StringBuilder avec comme Nom: Nom$ et Taille (En caractères): Taille.q.
; Il est conseillé de mèttre une taille assez grande pour pouvoir ajouter par la suite la ou les nouvelles Chaines de sorte à se que le programme ne sois pas obligé
; de réalouer automatiquement une taille plus grande pour pouvoir y ajouter la nouvelle Chaine, puisque ceci ralentie beaucoup le programme.
; Si le Nom est vide ou que celui-ci existe déjà alors la fonction échoura.
; Si la Taille est inférieur ou égale à 0 alors Taille vaudra 1.
; La Taille du StringBuilder est toujours en caractères.
; Renvoie 1 si le StringBuilder a été créer ou sinon 0.
Procedure.b CreateAndInitialiseMyStringBuilder(Nom$, Taille.q = 1)
  
  If Nom$ = "" Or FindMapElement(MapMyStringBuilder(), Nom$)
    ProcedureReturn 0
  EndIf
  
  If Taille.q <= 0
    Taille.q = 1
  EndIf
  
  If MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID = 0
    
    *MyStringBuilderMemoryID = AllocateMemory(StringByteLength(Space(Taille.q + 1), #PB_Unicode))
    
    If *MyStringBuilderMemoryID
      
      MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID = *MyStringBuilderMemoryID
      MemorySize.q = MemorySize(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID) / 2
      MemorySize.q - 1
      
      MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderRemaining = MemorySize.q
      MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize = MemorySize.q
      MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderPosition = 1
      
      ProcedureReturn 1
      
    Else
      ProcedureReturn 0
      
    EndIf
    
  Else
    ProcedureReturn 0
    
  EndIf
  
EndProcedure

; Vérifie que le StringBuilder existe avec comme Nom: Nom$.
; Si le Nom est vide ou que celui-ci n'existe pas alors la fonction échoura.
; Renvoie 1 si le StringBuilder éxiste ou sinon 0.
Procedure.b IsMyStringBuilder(Nom$)
  
  If Nom$ = "" Or Not FindMapElement(MapMyStringBuilder(), Nom$)
    ProcedureReturn 0
  Else
    ProcedureReturn  1
  EndIf
  
EndProcedure

; Ajoute une nouvelle chaine à la suite dans le StringBuilder avec comme Nom: Nom$ et Chaine: String.s.
; Si le Nom est vide ou que celui-ci n'existe pas alors la fonction échoura.
; Si la Chaine à ajouter est vide alors la fonction échoura.
; Renvoie 1 si la Chaine a été ajouté ou sinon 0.
Procedure.b MyStringBuilderAddString(Nom$, String.s)
  
  If IsMyStringBuilder(Nom$) And String.s > ""
    
    If Len(String.s) > MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderRemaining
      
      *MyStringBuilderMemoryID = ReAllocateMemory(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID, MemorySize(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID) + (StringByteLength(String.s) * 10))
      
      If *MyStringBuilderMemoryID
        
        MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID = *MyStringBuilderMemoryID
        
        MemorySize.q = MemorySize(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID) / 2
        MemorySize.q - 1
        
        If PokeS(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID + ((MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderPosition - 1) * 2), String.s, -1, #PB_Unicode)
          
          MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderRemaining = (MemorySize.q - (MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderPosition - 1) - Len(String.s))
          MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize = MemorySize.q
          MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderPosition + Len(String.s)
          
          ProcedureReturn 1
          
        Else
          ProcedureReturn 0
          
        EndIf
        
      Else
        ProcedureReturn 0
        
      EndIf
      
    Else
      
      MemorySize.q = MemorySize(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID) / 2
      MemorySize.q - 1
      
      If PokeS(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID + ((MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderPosition - 1) * 2), String.s, -1, #PB_Unicode)
        
        MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderRemaining = (MemorySize.q - (MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderPosition - 1) - Len(String.s))
        MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize = MemorySize.q
        MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderPosition + Len(String.s)
        
        ProcedureReturn 1
        
      Else
        ProcedureReturn 0
        
      EndIf
      
    EndIf
    
  Else
    ProcedureReturn 0
    
  EndIf
  
EndProcedure

; Change la Taille (En caractères) d'allocation du StringBuilder avec comme Nom: Nom$ et Taille: Taille.q.
; Attention, si la Taille spécifié est plus petite que celle actuel, la Chaine du StringBuilder à la fin de celui-ci serra alors raccourcir et ainsi, les données serront alors supprimé définitivement.
; Si le Nom est vide ou que celui-ci n'éxiste pas alors la fonction échoura.
; Si la Taille est inférieur ou égale à 0 alors Taille vaudra 1.
; La Taille du StringBuilder est toujours en caractères.
; Renvoie 1 si la Taille du StringBuilder a été changé ou sinon 0.
Procedure.b MyStringBuilderReAllocate(Nom$, Taille.q = 1)
  
  If IsMyStringBuilder(Nom$)
    
    If Taille.q <= 0
      Taille.q = 1
    EndIf
    
    AncienneTaille.q = MemorySize(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID) / 2
    AncienneTaille.q - 1
    
    *MyStringBuilderMemoryID = ReAllocateMemory(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID, StringByteLength(Space(Taille.q + 1)))
    
    If *MyStringBuilderMemoryID
      
      PokeS(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID + StringByteLength(Space(Taille.q)), Chr(#Null), -1, #PB_Unicode)
      
      MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID = *MyStringBuilderMemoryID
      MemorySize.q = (MemorySize(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID)) / 2
      MemorySize.q - 1
      
      TailleActuel.q = AncienneTaille.q
      NouvelleTaille.q = Taille.q
      Restant.q = MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderRemaining
      
      If TailleActuel.q > NouvelleTaille.q
        
        Difference.q = TailleActuel.q - NouvelleTaille.q
        Restant.q - Difference.q
        
        If Restant.q < 0
          MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderPosition + Restant.q
          Restant.q = 0
        EndIf
        
        MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderRemaining = Restant.q
        MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize = Taille.q
        
      ElseIf NouvelleTaille.q > TailleActuel.q
        
        Difference.q = NouvelleTaille.q - TailleActuel.q
        Restant.q + Difference.q
        
        MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderRemaining  = Restant.q
        MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize = Taille.q
        
      EndIf
      
      ProcedureReturn 1
      
    Else
      ProcedureReturn 0
      
    EndIf
    
  Else
    ProcedureReturn 0
    
  EndIf
  
EndProcedure

; Efface entièrement le StringBuilder avec comme Nom: Nom$.
; Si le Nom est vide ou que celui-ci n'existe pas alors la fonction échoura.
; Seule la Chaine du StringBuilder est éffacé, ça taille restera quand à elle inchangé, ceci ne supprime pas le StringBuilder.
; Renvoie 1 si le StringBuilder a été éffacé ou sinon 0.
Procedure.b MyStringBuilderClearString(Nom$)
  
  If IsMyStringBuilder(Nom$)
    
    MemorySize.q = MemorySize(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID) / 2
    MemorySize.q - 1
    
    FillMemory(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID, MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize, #Null , #PB_Unicode)
    
    MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderRemaining = MemorySize.q
    MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize = MemorySize.q
    MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderPosition = 1
    
    ProcedureReturn 1
    
  Else
    ProcedureReturn 0
    
  EndIf
  
EndProcedure

; Supprime le StringBuilder avec comme Nom: Nom$.
; Si le Nom est vide ou que celui-ci n'existe pas alors la fonction échoura.
; Attention, toutes les données du StringBuilder serront définitivement supprimé !
; Renvoie 1 si le StringBuilder a été supprimé ou sinon 0.
Procedure.b MyStringBuilderDeletteElement(Nom$)
  
  If IsMyStringBuilder(Nom$)
    DeleteMapElement(MapMyStringBuilder(), Nom$) 
    ProcedureReturn 1
    
  Else
    ProcedureReturn 0
    
  EndIf
  
EndProcedure

; Renvoie la partie de la chaine désiré du StringBuilder avec comme Nom: Nom$.
; La Position de Depart commance à 1, si celle-ci est inférieur ou égale à 0 alors celle-ci vaudra 1.
; Si la Position de Depart est supérieur à la longueur de la chaine actuellement stoqué dans le StringBuilder, alors celle-ci vaudra la longueur de la chaine actuellement stoqué dans le StringBuilder.
; La Longueur commance à 1, si celle-ci est inférieur à -1 alors celle-ci vaudra -1.
; Si la Longueur vaud -1 alors toutes la chaine stoqué dans le StringBuilder serra renvoyé.
; Si la Longueur est supérieur à la longueur de la chaine actuellement stoqué dans le StringBuilder, alors celle-ci vaudra la longueur de la chaine actuellement stoqué dans le StringBuilder.
; Si le Nom est vide ou que celui-ci n'existe pas alors la fonction renvéra une chaine vide.
Procedure.s MyStringBuilderGetString(Nom$, PositionDepart.q = 1, Longueur.q = -1)
  
  If IsMyStringBuilder(Nom$)
    
    If PositionDepart.q <= 1
      PositionDepart.q = 1
    EndIf
    
    If PositionDepart.q > MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize
      PositionDepart.q = MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize
    EndIf
    
    If Longueur.q < -1
      Longueur.q = -1
    EndIf
    
    If Longueur.q > MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize
      Longueur.q = (MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize)
    EndIf
    
    ProcedureReturn PeekS(MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID + ((PositionDepart.q - 1) * 2), Longueur.q, #PB_Unicode)
    
  Else
    ProcedureReturn ""
    
  EndIf
  
EndProcedure

; Renvoie l'adresse mémoire ou est stoqué la chaine dans le StringBuilder avec comme Nom: Nom$.
; Si le Nom est vide ou que celui-ci n'existe pas alors la fonction renvéra 0.
Procedure.i MyStringBuilderGetMemoryID(Nom$)
  
  If IsMyStringBuilder(Nom$)
    ProcedureReturn MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderMemoryID
    
  Else
    ProcedureReturn 0
    
  EndIf
  
EndProcedure

; Renvoie la Taille en caractères du StringBuilder avec comme Nom: Nom$.
; Si le Nom est vide ou que celui-ci n'existe pas alors la fonction renvéra 0.
Procedure.i MyStringBuilderGetSize(Nom$)
  
  If IsMyStringBuilder(Nom$)
    ProcedureReturn MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderSize
    
  Else
    ProcedureReturn 0
    
  EndIf
  
EndProcedure

; Renvoie l'espace restant en caractères du StringBuilder avec comme Nom: Nom$.
; Si le Nom est vide ou que celui-ci n'existe pas alors la fonction renvéra 0.
Procedure.i MyStringBuilderGetRemaining(Nom$)
  
  If IsMyStringBuilder(Nom$)
    ProcedureReturn MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderRemaining
    
  Else
    ProcedureReturn 0
    
  EndIf
  
EndProcedure

; Renvoie la Position en caractères du StringBuilder avec comme Nom: Nom$.
; Si le Nom est vide ou que celui-ci n'existe pas alors la fonction renvéra 0.
Procedure.i MyStringBuilderGetPosition(Nom$)
  
  If IsMyStringBuilder(Nom$)
    ProcedureReturn MapMyStringBuilder.StructureMyStringBuilder(Nom$)\MyStringBuilderPosition
    
  Else
    ProcedureReturn 0
    
  EndIf
  
EndProcedure

Chaine$ = "Abcdefghijklmnopqrstuvwxyz"
Chaine2$ = ""
MyStringBuilderName$ = "MyStringBuilder n°"

Time1 = ElapsedMilliseconds()

For I = 1 To 99
  
  If CreateAndInitialiseMyStringBuilder(MyStringBuilderName$ + Str(I), 1)
    
    If IsMyStringBuilder(MyStringBuilderName$ + Str(I))
      
      ;       MessageRequester("StringBuilder initialisation...", "StringBuilder Name = " + MyStringBuilderName$ + Str(I) + Chr(13) + Chr(10) +
      ;                                                           "StringBuilder MemoryID = " + Str(MyStringBuilderGetMemoryID(MyStringBuilderName$ + Str(I))) + Chr(13) + Chr(10) +
      ;                                                           "StringBuilder Memory Size = " + Str(MyStringBuilderGetSize(MyStringBuilderName$ + Str(I))) + Chr(13) + Chr(10) +
      ;                                                           "StringBuilder Memory Remaining = " + Str(MyStringBuilderGetRemaining(MyStringBuilderName$ + Str(I))) + Chr(13) + Chr(10) +
      ;                                                           "StringBuilder Memory Position = " + Str(MyStringBuilderGetPosition(MyStringBuilderName$ + Str(I))))
      
      ; Time1 = ElapsedMilliseconds()
      
      For J = 1 To 255
        
        Write.b = MyStringBuilderAddString(MyStringBuilderName$ + Str(I), Str(I) + Chaine$ + Str(J))
        MemoryID.q = MyStringBuilderGetMemoryID(MyStringBuilderName$ + Str(I))
        MemorySize.q = MyStringBuilderGetSize(MyStringBuilderName$ + Str(I))
        MemoryRemaining.q = MyStringBuilderGetRemaining(MyStringBuilderName$ + Str(I))
        MemoryPosition.q = MyStringBuilderGetPosition(MyStringBuilderName$ + Str(I))
        
        ;     
        ;     Debug "MemoryID: " + Str(MemoryID.q)
        ;     Debug "MemorySize: " + Str(MemorySize.q)
        ;     Debug "MemoryRemaining: " + Str(MemoryRemaining.q)
        ;     Debug "MemoryPosition: " + Str(MemoryPosition.q)
        ;     Debug "Write: " + Str(Write.b)
        ;     Debug "---------------------------"
        ;     
      Next
      
      ; Time2 = ElapsedMilliseconds()
      
      ;       MessageRequester("StringBuilder Résultat...", "StringBuilder Name = " + MyStringBuilderName$ + Str(I) + Chr(13) + Chr(10) +
      ;                                                     "StringBuilder MemoryID = " + Str(MyStringBuilderGetMemoryID(MyStringBuilderName$ + Str(I))) + Chr(13) + Chr(10) +
      ;                                                     "StringBuilder Memory Size = " + Str(MyStringBuilderGetSize(MyStringBuilderName$ + Str(I))) + Chr(13) + Chr(10) +
      ;                                                     "StringBuilder Memory Remaining = " + Str(MyStringBuilderGetRemaining(MyStringBuilderName$ + Str(I))) + Chr(13) + Chr(10) +
      ;                                                     "StringBuilder Memory Position = " + Str(MyStringBuilderGetPosition(MyStringBuilderName$ + Str(I))) + Chr(13) + Chr(10) +
      ;                                                     "Time Elapsed = " + Str(Time2 - Time1) + " Ms.")
      
      
    Else
      MessageRequester("StringBuilder Résultat...", "Erreur, Le StringBuilder: " + MyStringBuilderName$ + Str(I) + ", n'est pas initialisé !", 16)
      
    EndIf
    
  Else
    MessageRequester("StringBuilder Résultat...", "Erreur, Le StringBuilder: " + MyStringBuilderName$ + Str(I) + ", n'a pas put être crée !", 16)
    
  EndIf
  
Next

Time2 = ElapsedMilliseconds()

For i = 1 To 99
  Debug MyStringBuilderName$ + Str(I) + " = " + MyStringBuilderGetString(MyStringBuilderName$ + Str(I))
  Debug "----------"
Next

Debug "Time Elapsed = " + Str(Time2 - Time1) + " Ms."

Time1 = ElapsedMilliseconds()

; Juste 5000 au lieux des 255 * 99 = 25245
; Mettez 25245 pour voir le temps réel
For J = 1 To 5000
  Chaine2$ + Str(I) + Chaine$ + Str(J)
Next

Time2 = ElapsedMilliseconds()

Debug "Time Elapsed = " + Str(Time2 - Time1) + " Ms."

; ---------------------------------------------------------------------------------Exemple 2:---------------------------------------------------------------------------------------------------------------------------------------------------

; Chaine$ = "Abcdefghijklmnopqrstuvwxyz"
; Chaine2$ = ""
; MyStringBuilderName$ = "Mon StringBuilder"
; 
; Debug "Temps passé avec façon Normale = " + Str(Time2 - Time1) + " Ms."
; Debug "---------------------------------"
; 
; Time1 = ElapsedMilliseconds()
; 
; If CreateAndInitialiseMyStringBuilder(MyStringBuilderName$)
;   
;   If IsMyStringBuilder(MyStringBuilderName$)
;     
;     For I = 1 To 10000
;       MyStringBuilderAddString(MyStringBuilderName$, Chaine$ + Str(I))
;       
;     Next
;     
;   Else
;     MessageRequester("StringBuilder Résultat...", "Erreur, Le StringBuilder: " + MyStringBuilderName$ + Str(I) + ", n'est pas initialisé !", 16)
;     
;   EndIf
;   
; Else
;   MessageRequester("StringBuilder Résultat...", "Erreur, Le StringBuilder: " + MyStringBuilderName$ + Str(I) + ", n'a pas put être crée !", 16)
;   
; EndIf
; 
; Time2 = ElapsedMilliseconds()
; 
; Debug MyStringBuilderGetString(MyStringBuilderName$)
; Debug "Temps passé avec StringBuilder = " + Str(Time2 - Time1) + " Ms."
; Debug "---------------------------------"
; 
; Time1 = ElapsedMilliseconds()
; 
; ; Juste 5000 au lieux des 255 * 99 = 25245
; ; Mettez 25245 pour voir le temps réel
; For J = 1 To 5000
;   Chaine2$ + Str(I) + Chaine$ + Str(J)
; Next
; 
; Time2 = ElapsedMilliseconds()
; 
; Debug "Time Elapsed = " + Str(Time2 - Time1) + " Ms."
;
; MessageRequester("Temps", "Temps passé avec StringBuilder = " + Str(Time2 - Time1) + " Ms.", 64)
;
; ---------------------------------------------------------------------------------Exemple 3:---------------------------------------------------------------------------------------------------------------------------------------------------

; Chaine$ = "Abcdefghijklmnopqrstuvwxyz"
; Chaine2$ = ""
; MyStringBuilderName$ = "Mon StringBuilder"
; ; 
; ; Time1 = ElapsedMilliseconds()
; ; 
; ; For J = 1 To 10000
; ;   Chaine2$ + Str(I) + Chaine$ + Str(J)
; ; Next
; ; 
; ; Time2 = ElapsedMilliseconds()
; ; 
; ; Debug Chaine2$
; ; Debug "Temps passé avec façon normale = " + Str(Time2 - Time1) + " Ms."
; ; Debug "---------------------------------"
; 
; Time1 = ElapsedMilliseconds()
; 
; If CreateAndInitialiseMyStringBuilder(MyStringBuilderName$, 100000000)
;   
;   If IsMyStringBuilder(MyStringBuilderName$)
;     
;     For I = 1 To 1000000
;       MyStringBuilderAddString(MyStringBuilderName$, Chaine$ + Str(I))
;       
;     Next
;     
;   Else
;     MessageRequester("StringBuilder Résultat...", "Erreur, Le StringBuilder: " + MyStringBuilderName$ + Str(I) + ", n'est pas initialisé !", 16)
;     
;   EndIf
;   
; Else
;   MessageRequester("StringBuilder Résultat...", "Erreur, Le StringBuilder: " + MyStringBuilderName$ + Str(I) + ", n'a pas put être crée !", 16)
;   
; EndIf
; 
; Time2 = ElapsedMilliseconds()
; 
; Debug MyStringBuilderGetString(MyStringBuilderName$)
; Debug "Temps passé avec StringBuilder = " + Str(Time2 - Time1) + " Ms."
; Debug "---------------------------------"
;
; MessageRequester("Temps", "Temps passé avec StringBuilder = " + Str(Time2 - Time1) + " Ms.", 64)
I am French, I do not speak English.
My apologies for the mistakes.

I have sometimes problems of expression
I am sometimes quite clumsy, please excuse me and let me know.
Post Reply