String.s{} Begrenzung nachträglich ändern

Anfängerfragen zum Programmieren mit PureBasic.
¯\_(ツ)_/¯
Beiträge: 141
Registriert: 18.08.2017 09:35

String.s{} Begrenzung nachträglich ändern

Beitrag von ¯\_(ツ)_/¯ »

Folgender Code funzt gut:

Code: Alles auswählen

Define Str.s{5}


Str = "hallowelt"
Debug Str
Kann man die Begrenzung später noch ändern?

Code: Alles auswählen

Define Str.s{5}
Define Str.s{10}
geht leider nicht...
Bild
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: String.s{} Begrenzung nachträglich ändern

Beitrag von RSBasic »

Alternativ könntest du {} weglassen und stattdessen mit Left() oder Mid() arbeiten.
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
¯\_(ツ)_/¯
Beiträge: 141
Registriert: 18.08.2017 09:35

Re: String.s{} Begrenzung nachträglich ändern

Beitrag von ¯\_(ツ)_/¯ »

Okay
Bild
Lord
Beiträge: 313
Registriert: 21.01.2008 19:11

Re: String.s{} Begrenzung nachträglich ändern

Beitrag von Lord »

Dieser Vergleich ist ja interessant (ohne Debugger!):

Code: Alles auswählen

T$="Teststring"
Define s1.s{4}
t1=ElapsedMilliseconds()
For i=1 To 100000000
  s1=T$
Next
t2=ElapsedMilliseconds()
MessageRequester("", Str(t2-t1)+" ms")
und

Code: Alles auswählen

T$="Teststring"
Define s1.s
t1=ElapsedMilliseconds()
For i=1 To 100000000
  s1=Left(T$,4)
Next
t2=ElapsedMilliseconds()
MessageRequester("", Str(t2-t1)+" ms")
4266 ms zu 8640 ms auf meinem Rechner.
Das war mir so noch nicht bekannt.
Wenn man also statt Left() s.s{} benutzt, hat man einen deutlichen Zeitgewinn.
Bild
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: String.s{} Begrenzung nachträglich ändern

Beitrag von RSBasic »

Mid() ist etwas schneller als Left(), aber nur minimal.

Mit Assembler sollte es schneller sein, als Mid(): http://www.purebasic.fr/english/viewtop ... 12&t=24132
Aber leider funktionieren die Codes nicht mehr und ich habe auch keine Ahnung, wie man den Code zum Laufen kriegt.
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Lord
Beiträge: 313
Registriert: 21.01.2008 19:11

Re: String.s{} Begrenzung nachträglich ändern

Beitrag von Lord »

Hallo Ray!
RSBasic hat geschrieben:...
Aber leider funktionieren die Codes nicht mehr ...
Versuchs mal hiermit:

Code: Alles auswählen

! macro EndMacro {}

; Assembler macro to align code on a given boundary,
; aligning loop starts on 8 byte boundaries can speed up the code
; by about 1.5 to 2 times!

! macro calignjmp value
! {
!   local dest
!
!   if ((value - 1) - ((($ - $$) + value - 1) mod value)) > 3
!     makeDest equ 1
!     jmp dest
!   else
!     makeDest equ 0
!   end if
!
!   rept value
!   \{
!     if ($ - $$) mod value
!       nop
!     end if
!   \}
!   dest:
! } EndMacro

; Uncommend the next 3 lines, if you want to replace
; Mid with FMid in all places:
; Macro Mid(string, start, length)
;   FMid2(@string,start,length)
; EndMacro

CompilerIf #PB_Compiler_Unicode
Procedure.s FMid2(*srcPtr.Byte, start.l, length.l)
  !MOV    edx,[p.p_srcPtr]
  !MOV    ecx,[p.v_length]
  !TEST   edx,edx
  !JZ     ll_fmid2_empty
  !TEST   ecx,ecx
  !JLE    ll_fmid2_empty
  !MOV    ecx,[p.v_start]
  !CMP    ecx,1
  !JLE    ll_fmid2_fmid2return
  !XOR    eax,eax
  !DEC    ecx
  !calignjmp 4
  scan1:
  !SUB    ecx,8
  !JL     ll_fmid2_scanend1
  !CMP    [edx],ax
  !JE     ll_fmid2_scanend2
  !ADD    edx,2
  !CMP    [edx],ax
  !JE     ll_fmid2_scanend2
  !ADD    edx,2
  !CMP    [edx],ax
  !JE     ll_fmid2_scanend2
  !ADD    edx,2
  !CMP    [edx],ax
  !JE     ll_fmid2_scanend2
  !ADD    edx,2
  !CMP    [edx],ax
  !JE     ll_fmid2_scanend2
  !ADD    edx,2
  !CMP    [edx],ax
  !JE     ll_fmid2_scanend2
  !ADD    edx,2
  !CMP    [edx],ax
  !JE     ll_fmid2_scanend2
  !ADD    edx,2
  !CMP    [edx],ax
  !JE     ll_fmid2_scanend2
  !ADD    edx,2
  !JMP    ll_fmid2_scan1

  scanend1:
  !ADD    ecx,8
  !JZ     ll_fmid2_scanend2
  scan2:
  !CMP    [edx],ax
  !JE     ll_fmid2_scanend2
  !ADD    edx,2
  !DEC    ecx
  !JNZ    ll_fmid2_scan2
  scanend2:
  !MOV   [p.p_srcPtr],edx
  fmid2return:
  ProcedureReturn PeekS(*srcPtr, length)
  empty:
  ProcedureReturn ""
EndProcedure
CompilerElse
Procedure.s FMid2(*srcPtr.Byte, start.l, length.l)
  !MOV    edx,[p.p_srcPtr]
  !MOV    ecx,[p.v_length]
  !TEST   edx,edx
  !JZ     ll_fmid2_empty
  !TEST   ecx,ecx
  !JLE    ll_fmid2_empty
  !MOV    ecx,[p.v_start]
  !CMP    ecx,1
  !JLE    ll_fmid2_fmid2return
  !XOR    eax,eax
  !DEC    ecx
  !calignjmp 4
  scan1:
  !SUB    ecx,8
  !JL     ll_fmid2_scanend1
  !CMP    [edx],al
  !JE     ll_fmid2_scanend2
  !INC    edx
  !CMP    [edx],al
  !JE     ll_fmid2_scanend2
  !INC    edx
  !CMP    [edx],al
  !JE     ll_fmid2_scanend2
  !INC    edx
  !CMP    [edx],al
  !JE     ll_fmid2_scanend2
  !INC    edx
  !CMP    [edx],al
  !JE     ll_fmid2_scanend2
  !INC    edx
  !CMP    [edx],al
  !JE     ll_fmid2_scanend2
  !INC    edx
  !CMP    [edx],al
  !JE     ll_fmid2_scanend2
  !INC    edx
  !CMP    [edx],al
  !JE     ll_fmid2_scanend2
  !INC    edx
  !JMP    ll_fmid2_scan1

  scanend1:
  !ADD    ecx,8
  !JZ     ll_fmid2_scanend2
  scan2:
  !CMP    [edx],al
  !JE     ll_fmid2_scanend2
  !INC    edx
  !DEC    ecx
  !JNZ    ll_fmid2_scan2
  scanend2:
  !MOV   [p.p_srcPtr],edx
  fmid2return:
  ProcedureReturn PeekS(*srcPtr, length)
  fmid2_empty:
  ProcedureReturn ""
EndProcedure
CompilerEndIf


OpenConsole()

Global tStart.l, tStart2.l, tDiff.d
Global str1.s, str1Pos.l, str1Len.l = 4096, str1Mid.s, str1FMid.s
Global i.l, iEnd.l, strCh.l
Global start.l, length.l

strCh = 1
For i = 1 To str1Len
  str1 + Chr(strCh)
  strCh + 1
  If strCh > 255: strCh = 1: EndIf
Next i

iEnd = 10000
For i = 1 To iEnd
  start = Random(10000)-5000
  length = Random(10000)-5000
  str1Mid = Mid(str1, start, length)
  str1FMid = FMid2(@str1, start, length)
  If str1Mid <> str1FMid
    PrintN("Error FMid: " + Str(start) + ", " + Str(length))
    CallDebugger
  EndIf
Next i

iEnd = 10000
For i = 1 To iEnd
  start = Random(10000)-5000
  length = Random(10000)-5000
  str1Mid = Mid(str1, start, length)
  str1FMid = FMid2(@str1, start, length)
  If str1Mid <> str1FMid
    PrintN("Error FMid2: " + Str(start) + ", " + Str(length))
    CallDebugger
  EndIf
Next i

PrintN(#CRLF$ + "Done")
While Inkey() = "": Delay(100): Wend

Bild
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: String.s{} Begrenzung nachträglich ändern

Beitrag von RSBasic »

Hallo Lord,

vielen Dank für die Anpassung des Codes auf die neuste Version. :allright:
Ich werde gleich mal deinen Code mit dem originalen Code vergleichen, damit ich sehen kann, was du geändert hast, so dass ich weiß, woran es lag, warum der alte Code mit der neuen PB-Version nicht ging.

Ich habe deinen Zeittest-Code mit FMid2() getestet, aber leider scheint es mit Assembler auch nicht schneller zu sein.

Code: Alles auswählen

T$="Teststring"
Define s1.s
t1=ElapsedMilliseconds()
For i=1 To 100000000
  s1=FMid2(@T$, 1, 4)
Next
t2=ElapsedMilliseconds()
MessageRequester("", Str(t2-t1)+" ms")
Also ist die schnellste Variante nur mit s.s{}.
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
oO0XX0Oo
Beiträge: 55
Registriert: 21.07.2017 22:36

Re: String.s{} Begrenzung nachträglich ändern

Beitrag von oO0XX0Oo »

@Lord

Nur aus Neugier: Stimmen die Angaben von deinem System noch (i5, Win7, PB Version)?

Auf einem i5 System (4 GHZ, 32 GB, Windows Server 2012 R2, PB 5.62, Debugger disabled)
brauchen die beiden Routinen ca. 10 / 20 Sekunden. Dein System müsste deshalb eigentlich
eher doppelt so schnell sein...
Lord
Beiträge: 313
Registriert: 21.01.2008 19:11

Re: String.s{} Begrenzung nachträglich ändern

Beitrag von Lord »

Hi!
RSBasic hat geschrieben:...
Ich habe deinen Zeittest-Code mit FMid2() getestet, aber leider scheint es mit Assembler auch nicht schneller zu sein.
...
Ich habe diesmal die FMid2() und Mid() hiermit laufen lassen:

Code: Alles auswählen

S.s="teststring"
e.s=""
t1=ElapsedMilliseconds()
For i=1 To 100000000
 e=Mid(s, 1, 4)
Next
t2=ElapsedMilliseconds()
For i=1 To 100000000
 e=fMid2(@s, 1, 4)
Next
t3=ElapsedMilliseconds()

MessageRequester("", Str(t2-t1)+" ms"+#CRLF$+Str(t3-t2)+" ms")
Das Resultat auf meinem Rechner unter
PB 5.60x64 7481 ms zu 7739 ms
PB 5.60x86 8590 ms zu 8615 ms

Mid() ist also bei mir hier minmal schneller als FMid2().
Damit ist die Variante mit s{} also als Left()-Ersatz vielleicht vorzuziehen.
Ich bin aber kein ASM-Mensch, so daß ich nicht sagen kann, oder ASM-Code irgendwie optimiert ist oder noh optimiert werden kann.
Bild
Lord
Beiträge: 313
Registriert: 21.01.2008 19:11

Re: String.s{} Begrenzung nachträglich ändern

Beitrag von Lord »

oO0XX0Oo hat geschrieben:@Lord

Nur aus Neugier: Stimmen die Angaben von deinem System noch (i5, Win7, PB Version)?

Auf einem i5 System (4 GHZ, 32 GB, Windows Server 2012 R2, PB 5.62, Debugger disabled)
brauchen die beiden Routinen ca. 10 / 20 Sekunden. Dein System müsste deshalb eigentlich
eher doppelt so schnell sein...
???

Wieso sollte mein Recher mit i5@2.8GHz, 16GB, Win7, PB5.60 doppelt so schnell sein?
Und ja, der Debugger war auch aus.
Bild
Antworten