String Zeichen für Zeichen durch arbeiten

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: String Zeichen für Zeichen durch arbeiten

Beitrag von ts-soft »

Christian H hat geschrieben:@ts-soft deine Array Variante ist bei mir schneller als die "Structure char"-Variante
Stimmt, macht den Test in 35 ms. Äußerst merkwürdig, dann würde ich das doch nehmen, bietet ja auch
Zugriff auf einzelen Zeichen ohne Schleife, was die anderen, gleich schnellen nicht bieten.
Aber das die Char-Varianten langsamer ist verblufft mich ganz schön.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Christian H
Beiträge: 134
Registriert: 18.10.2005 10:22
Wohnort: Welschbillig

Re: String Zeichen für Zeichen durch arbeiten

Beitrag von Christian H »

bei der Array Variante wird zwar mehr Speicher verbraucht aber das sollte Heute nichts mehr ausmachen.
Teste mal mit "String.s = LSet("", 10*1024, "@")" da werden die Unterschiede bei mir deutlicher.

Gruß Christian
Benutzeravatar
CSHW89
Beiträge: 489
Registriert: 14.12.2008 12:22

Re: String Zeichen für Zeichen durch arbeiten

Beitrag von CSHW89 »

ts-soft hat geschrieben:
Christian H hat geschrieben:@ts-soft deine Array Variante ist bei mir schneller als die "Structure char"-Variante
Stimmt, macht den Test in 35 ms. Äußerst merkwürdig, dann würde ich das doch nehmen, bietet ja auch
Zugriff auf einzelen Zeichen ohne Schleife, was die anderen, gleich schnellen nicht bieten.
Aber das die Char-Varianten langsamer ist verblufft mich ganz schön.
Wenn du damit 'test2' meinst, dort ist im ausdruck nach 'To' wieder ein Methodenaufruf 'Len()'. wenn die Länge in einer variable vorher speicherst, ist die methode ca. gleich schnell, wie die anderen.

Code: Alles auswählen

Procedure Test2(Text.s)
  ;ts-soft

  Protected *char.char
  Protected i, len
  Protected temp.s

  *char = @Text
  
  len = Len(Text)-1
  
  For i = 0 To len
    temp = Chr(*char\c[i])
  Next
EndProcedure
lg kevin
Bild Bild Bild
http://www.jasik.de - Windows Hilfe Seite
padawan hat geschrieben:Ich liebe diese von hinten über die Brust ins Auge Lösungen
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: String Zeichen für Zeichen durch arbeiten

Beitrag von ts-soft »

@CSHW89
Hab jetzt nicht dran gedacht, das PB die For Next Schleife dynamisch auswertet :freak:
Wäre sie Konstant, wäre die For Next Schleife auch schneller. Für dynamische Schleifen
nimmt man ja eigentlich While Wend oder Repeat Until.
Da haben wohl ein paar Anwender gemeckert, so das dieses IMHO unnütze Feature eingebaut
wurde.

Danke für den Hinweis.

Gruß
Thomas
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Friedhelm
Beiträge: 43
Registriert: 29.08.2004 08:50

Re: String Zeichen für Zeichen durch arbeiten

Beitrag von Friedhelm »

Code: Alles auswählen

Procedure  test1(Text.s)
    ; Christian H  For Next 1
    TAdr.i = @Text
    TEnd.i = TAdr+StringByteLength(Text)-SizeOf(Character)
    For i = TAdr To TEnd Step SizeOf(Character)
        temp.s = Chr(PeekC(i))
    Next
   
EndProcedure

Procedure  test12(Text.s)
; Christian H  For Next 2
    TAdr.i = @Text
   
    For i = TAdr To TAdr+StringByteLength(Text)-1 Step #PB_Compiler_Unicode+1
        temp.s = Chr(PeekC(i))
    Next   
EndProcedure

Procedure  test13(Text.s)
    ; Christian H  For Next Len+Mid   
    For i = 1 To Len(Text)
        temp.s = Mid(Text,i,1)
    Next   
EndProcedure

Structure char
  c.c[0]
EndStructure

Procedure Test2(Text.s)
  ;ts-soft

  Protected *char.char
  Protected i
  Protected temp.s

  *char = @Text
   
  For i = 0 To  Len(Text)-1
    temp = Chr(*char\c[i])
  Next
EndProcedure

Procedure Test22(Text.s)
  ;ts-soft

  Protected *char.char
  Protected i
  Protected temp.s

  *char = @Text
    len = Len(Text)-1
  For i = 0 To Len
    temp = Chr(*char\c[i])
  Next
EndProcedure

Procedure Test3(Text.s)
  ; ts-soft Array Variante
  Dim TextArray.c(Len(Text))
  CopyMemory(@Text, @TextArray(0), StringByteLength(Text))

  len.i = ArraySize(TextArray())
  For i = 0 To len
     temp.s = Chr( TextArray(i) )
  Next
EndProcedure

Procedure Test4(Text.s)
   ; milan1612
 
  *current.Character = @Text

  While *current\c <> 0
    temp.s = Chr(*current\c)
    *current + SizeOf(Character)
  Wend
EndProcedure

Procedure Test5(Text.s)
  ;Friedhelm  For Next

 Protected *pos.Character ,*lenstart,*lenende
 Protected temp

   *len_start  = @Text
    *len_ende  = Len(Text)-1+*len_start
    
  For *pos = *len_start To *len_ende Step #PB_Compiler_Unicode+1
    temp = *pos\c
        
  Next
EndProcedure

Procedure Test6 (*Text.Character)
  ;Friedhelm IF

Start_IF:
If *Text\c <> 0   
   temp = *Text\c
    *Text+#PB_Compiler_Unicode+1
Goto  Start_IF   
EndIf 

EndProcedure




String.s = LSet("", 1000, "@")
Time=10000

StartTime1 = ElapsedMilliseconds() 
For n = 1 To Time
  test1(String) ;Christian H
Next
EndTime1 = ElapsedMilliseconds()

Delay(100)

StartTime12 = ElapsedMilliseconds() 
For n = 1 To Time
  test12(String) ;Christian H
Next
EndTime12 = ElapsedMilliseconds()

Delay(100)

StartTime13 = ElapsedMilliseconds() 
For n = 1 To Time
  test13(String) ;Christian H  For Next Len+Mid
Next
EndTime13 = ElapsedMilliseconds()

Delay(100)

StartTime2 = ElapsedMilliseconds() 
For n = 1 To Time
  test2(String) ; ts-soft
Next
EndTime2 = ElapsedMilliseconds()

Delay(100)

StartTime22 = ElapsedMilliseconds() 
For n = 1 To Time
  test22(String) ; ts-soft
Next
EndTime22 = ElapsedMilliseconds()

Delay(100)

StartTime3 = ElapsedMilliseconds() 
For n = 1 To Time
  test3(String)  ; ts-soft Array Variante
Next
EndTime3 = ElapsedMilliseconds()

Delay(100)

StartTime4 = ElapsedMilliseconds() 
For n = 1 To Time
  test4(String)  ; milan1612 / Kaeru Gaman
Next
EndTime4 = ElapsedMilliseconds()

Delay(100)

StartTime5 = ElapsedMilliseconds() 
For n = 1 To Time
  test5(String)  ; Friedhelms For 
Next
EndTime5 = ElapsedMilliseconds()

Delay(100)

StartTime6 = ElapsedMilliseconds() 
For n = 1 To Time
  test6(@String)  ; Friedhelms IF  
Next
EndTime6 = ElapsedMilliseconds()



message.s = "Christian H  For Next 1         = "+Str(EndTime1 -StartTime1 )+"ms"+#CRLF$
message.s + "Christian H  For Next 2         = "+Str(EndTime12-StartTime12)+"ms"+#CRLF$
message.s + "Christian H  For Next Len+Mid   = "+Str(EndTime13-StartTime13)+"ms"+#CRLF$
message.s + "ts-soft                         = "+Str(EndTime2 -StartTime2 )+"ms"+#CRLF$
message.s + "ts-soft len op                  = "+Str(EndTime22-StartTime22)+"ms"+#CRLF$
message.s + "ts-soft Array                   = "+Str(EndTime3 -StartTime3 )+"ms"+#CRLF$
message.s + "milan1612                       = "+Str(EndTime4 -StartTime4 )+"ms"+#CRLF$
message.s + "Friedhelms For Next             = "+Str(EndTime5 -StartTime5 )+"ms"+#CRLF$
message.s + "Friedhelms IF                   = "+Str(EndTime6 -StartTime6 )+"ms"+#CRLF$

MessageRequester("Zeit", message.s)
; IDE Options = PureBasic 4.40 (Windows - x86)
; CursorPosition = 72
; FirstLine = 37
; Folding = -
; EnableUnicode
; DisableDebugger
nochmal der Zusammenfassung der Testroutinen.
Und meine Testroutinen hinzugefügt.
Bin gespannt auf eure Messwerte!
mfg
Friedhelm
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: String Zeichen für Zeichen durch arbeiten

Beitrag von ts-soft »

@Friedhelm
Da brauch ich nicht testen, Dein temp ist kein String, es fehlt also eine Geschwindigkeitsentscheidende
Funktion :wink:

geschummelt, geschummelt :lol:
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Friedhelm
Beiträge: 43
Registriert: 29.08.2004 08:50

Re: String Zeichen für Zeichen durch arbeiten

Beitrag von Friedhelm »

ts-soft hat geschrieben:@Friedhelm
Da brauch ich nicht testen, Dein temp ist kein String, es fehlt also eine Geschwindigkeitsentscheidende
Funktion :wink:

geschummelt, geschummelt :lol:
@ts-soft
Da habe ich wohl nicht richtig aufgepasst /:->



Ich Versuchs nochmal mit geänderten Routinen und denke das es flott ist!.
Bin gespannt auf eure Messwerte!.


Code: Alles auswählen

Procedure  test1(Text.s)
    ; Christian H  For Next 1
    TAdr.i = @Text
    TEnd.i = TAdr+StringByteLength(Text)-SizeOf(Character)
    For i = TAdr To TEnd Step SizeOf(Character)
        temp.s = Chr(PeekC(i))
    Next
   
EndProcedure

Procedure  test12(Text.s)
; Christian H  For Next 2
    TAdr.i = @Text
   
    For i = TAdr To TAdr+StringByteLength(Text)-1 Step #PB_Compiler_Unicode+1
        temp.s = Chr(PeekC(i))
    Next   
EndProcedure

Procedure  test13(Text.s)
    ; Christian H  For Next Len+Mid   
    For i = 1 To Len(Text)
        temp.s = Mid(Text,i,1)
    Next   
EndProcedure

Structure char
  c.c[0]
EndStructure

Procedure Test2(Text.s)
  ;ts-soft

  Protected *char.char
  Protected i
  Protected temp.s

  *char = @Text
   
  For i = 0 To  Len(Text)-1
    temp = Chr(*char\c[i])
  Next
EndProcedure

Procedure Test22(Text.s)
  ;ts-soft

  Protected *char.char
  Protected i
  Protected temp.s

  *char = @Text
    len = Len(Text)-1
  For i = 0 To Len
    temp = Chr(*char\c[i])
  Next
EndProcedure

Procedure Test3(Text.s)
  ; ts-soft Array Variante
  Dim TextArray.c(Len(Text))
  CopyMemory(@Text, @TextArray(0), StringByteLength(Text))

  len.i = ArraySize(TextArray())
  For i = 0 To len
     temp.s = Chr( TextArray(i) )
  Next
EndProcedure

Procedure Test4(Text.s)
   ; milan1612

  *current.Character = @Text

  While *current\c <> 0
    temp.s = Chr(*current\c)
    *current + SizeOf(Character)
  Wend
EndProcedure

Procedure Test5(Text.s)
  ;Friedhelm  For Next

Static *pos.Character 
Static temp.s=" ",*len_start,*len_ende

   *len_start  = @Text
    *len_ende  = Len(Text)+*len_start
   
  For *pos = *len_start To *len_ende Step #PB_Compiler_Unicode+1
   
     PokeC(@temp,*pos\c)
 
  Next
EndProcedure

Procedure Test6 (*Text.Character)
  ;Friedhelm IF

Static temp.s=" "

Start_IF:
If *Text\c <> 0   
   PokeC(@temp, *Text\c)
    *Text+#PB_Compiler_Unicode+1
Goto  Start_IF   
EndIf

EndProcedure




String.s = LSet("", 1000, "@")
Time=10000

StartTime1 = ElapsedMilliseconds()
For n = 1 To Time
  test1(String) ;Christian H
Next
EndTime1 = ElapsedMilliseconds()

Delay(100)

StartTime12 = ElapsedMilliseconds()
For n = 1 To Time
  test12(String) ;Christian H
Next
EndTime12 = ElapsedMilliseconds()

Delay(100)

StartTime13 = ElapsedMilliseconds()
For n = 1 To Time
  test13(String) ;Christian H  For Next Len+Mid
Next
EndTime13 = ElapsedMilliseconds()

Delay(100)

StartTime2 = ElapsedMilliseconds()
For n = 1 To Time
  test2(String) ; ts-soft
Next
EndTime2 = ElapsedMilliseconds()

Delay(100)

StartTime22 = ElapsedMilliseconds()
For n = 1 To Time
  test22(String) ; ts-soft
Next
EndTime22 = ElapsedMilliseconds()

Delay(100)

StartTime3 = ElapsedMilliseconds()
For n = 1 To Time
  test3(String)  ; ts-soft Array Variante
Next
EndTime3 = ElapsedMilliseconds()

Delay(100)

StartTime4 = ElapsedMilliseconds()
For n = 1 To Time
  test4(String)  ; milan1612 / Kaeru Gaman
Next
EndTime4 = ElapsedMilliseconds()

Delay(100)

StartTime5 = ElapsedMilliseconds()
For n = 1 To Time
  test5(String)  ; Friedhelms For
Next
EndTime5 = ElapsedMilliseconds()

Delay(100)

StartTime6 = ElapsedMilliseconds()
For n = 1 To Time
  test6(@String)  ; Friedhelms IF 
Next
EndTime6 = ElapsedMilliseconds()



message.s = "Christian H  For Next 1         = "+Str(EndTime1 -StartTime1 )+"ms"+#CRLF$
message.s + "Christian H  For Next 2         = "+Str(EndTime12-StartTime12)+"ms"+#CRLF$
message.s + "Christian H  For Next Len+Mid   = "+Str(EndTime13-StartTime13)+"ms"+#CRLF$
message.s + "ts-soft                         = "+Str(EndTime2 -StartTime2 )+"ms"+#CRLF$
message.s + "ts-soft len op                  = "+Str(EndTime22-StartTime22)+"ms"+#CRLF$
message.s + "ts-soft Array                   = "+Str(EndTime3 -StartTime3 )+"ms"+#CRLF$
message.s + "milan1612                       = "+Str(EndTime4 -StartTime4 )+"ms"+#CRLF$
message.s + "Friedhelms For Next             = "+Str(EndTime5 -StartTime5 )+"ms"+#CRLF$
message.s + "Friedhelms IF                   = "+Str(EndTime6 -StartTime6 )+"ms"+#CRLF$

MessageRequester("Zeit", message.s)
; IDE Options = PureBasic 4.40 (Windows - x86)
; CursorPosition = 72
; FirstLine = 37
; Folding = -
; EnableUnicode
; DisableDebugger
mfg
Friedhelm
Christian H
Beiträge: 134
Registriert: 18.10.2005 10:22
Wohnort: Welschbillig

Re: String Zeichen für Zeichen durch arbeiten

Beitrag von Christian H »

Wenn das mal nicht ne' Steigerung ist.

Code: Alles auswählen

;MessageRequester("Zeit", message.s)

OpenConsole()
Print(message.s)
PrintN("Press any key to exit"): Repeat: Until Inkey() <> ""

; Christian H  For Next 1         =  1281ms
; Christian H  For Next 2         = 17297ms
; Christian H  For Next Len+Mid   = 27578ms
; ts-soft                         = 15281ms
; ts-soft len op                  =  1281ms
; ts-soft Array                   =  1266ms
; milan1612                       =  1250ms
; Friedhelms For Next             =   125ms <--- Lösung nicht richtig!
; Friedhelms If                   =   125ms
Aber die Test5() ";Friedhelm For Next" gibt bei einem Test nur den halben Text aus:

Code: Alles auswählen

Procedure Test5(Text.s)
  ;Friedhelm  For Next

Static *pos.Character
Static temp.s=" ",*len_start,*len_ende

   *len_start  = @Text
    *len_ende  = Len(Text)+*len_start
   
  For *pos = *len_start To *len_ende Step #PB_Compiler_Unicode+1
   
     PokeC(@temp,*pos\c)
     Debug temp ; <----------
  Next
EndProcedure

String.s = "-ABCDEFGHIJKLMNOPQRSTUVW"

test5(String)  ; Friedhelms For Next
Gruß Christian
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8807
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: String Zeichen für Zeichen durch arbeiten

Beitrag von NicTheQuick »

Das passiert, wenn man Unicode verwendet und das Ende des Strings im Speicher nicht richtig berechnet. Diese Zeile ist falsch:

Code: Alles auswählen

*len_ende  = Len(Text)+*len_start
Diese wäre richtig:

Code: Alles auswählen

*len_ende = Sizeof(Character) * Len(Text) + *len_start
Oder diese hier:

Code: Alles auswählen

*len_ende = StringByteLength(Text) + *len_start
Christian H
Beiträge: 134
Registriert: 18.10.2005 10:22
Wohnort: Welschbillig

Re: String Zeichen für Zeichen durch arbeiten

Beitrag von Christian H »

NicTheQuick hat geschrieben:Das passiert, wenn man Unicode verwendet und das Ende des Strings im Speicher nicht richtig berechnet.
Danke :) Ich glaub das war Jedem in diesem Thread klar.
Ich wollte Friedhelm nur darauf aufmerksam machen das seine "Nachlässigkeit" ihn schon wieder zum Schummler gemacht hat :mrgreen:

@FriedhelmDu bist dennoch Auf Platz 1 u. 2

Gruß Christian
Antworten