Speedtests: MeinString$="" vs. Len(MeinString$)=0

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Speedtests: MeinString$="" vs. Len(MeinString$)=0

Beitrag von Kiffi »

Hallo

hiermit möchte ich einen Thread eröffnen, in dem es darum geht,
verschiedene Programmiertechniken gegenüberzustellen und sie in Bezug
auf deren Geschwindigkeit zu untersuchen. Ich fange mal mit einem
einfachen Beispiel an:

Es kommt nicht gerade selten vor, dass ein Programmierer testen muss,
ob ein String einen Inhalt hat oder leer ist. Normalerweise geschieht dies
mit einem Vergleich auf einen Leerstring:

Code: Alles auswählen

; Variante 1
If MeinString$ = ""
ebenso könnte man auch testen, ob der String eine Länge von 0 hat. Dann
ist er ebenfalls leer:

Code: Alles auswählen

; Variante 2
If Len(MeinString$) = 0
VB-Programmierer werden vermutlich wissen, dass in Ihrer Sprache
Variante 2 die eindeutig schnellere ist, denn VB generiert in Variante 1
zunächst einen Leerstring, um ihn dann mit MeinString$ zu vergleichen.
Diese zeitaufwendige Stringgenerierung fällt in Variante 2 weg.

Doch wie sieht's in PB aus. Welche Variante ist hier zu bevorzugen?

Um das Ergebnis vorwegzunehmen: Variante 1 ist in diesem Vergleich der
klare Geschwindigkeitssieger. Und: je länger der zu testende String ist,
desto deutlicher wird der Zeitunterschied.

Code: Alles auswählen

; Speedtest 1
; Prüfung, ob String leer ist

NewList ST_Check_1.l()
NewList ST_Check_2.l()

sDummy$ = Space(255)

For Schleife = 0 To 20

  ; ##################################
  ; Prüfung mittels Len(MeinString) = 0
  ; ##################################
  
  Z1 = ElapsedMilliseconds()
  
  For Counter = 0 To 1000000
    If Len(sDummy$)=0 : EndIf
  Next Counter
  
  Z2 = ElapsedMilliseconds()
  
  AddElement(ST_Check_1()) : ST_Check_1()=Z2-Z1
  
  ; ##################################
  ; Prüfung mittels MeinString = ""
  ; ##################################
  
  Z1 = ElapsedMilliseconds()
  
  For Counter = 0 To 1000000
    If sDummy$="" : EndIf
  Next Counter
  
  Z2 = ElapsedMilliseconds()
  
  AddElement(ST_Check_2()) : ST_Check_2()=Z2-Z1

Next

; ##################################
; Prüfung abgeschlossen
; hier kommt die Ausgabe:
; ##################################

sMessage$ = ""

For Schleife = 0 To 20
  
  SelectElement(ST_Check_1(), Schleife)
  SelectElement(ST_Check_2(), Schleife)
  
  sMessage$ + Str(ST_Check_1()) + " / " + Str(ST_Check_2()) + #CRLF$
  
Next

MessageRequester("", sMessage$)
Grüße ... Kiffi
a²+b²=mc²
Benutzeravatar
bobobo
jaAdmin
Beiträge: 3873
Registriert: 13.09.2004 17:48
Kontaktdaten:

Beitrag von bobobo »

Es ist mir irgendwie leicht reinlaufend, dass ne Funktion irgendwie lahmer ist als ne direkte Zuweisung. Ich fahr doch auch nicht von Bielefeld nach Brackwede über Berlin. Bin aber auch nicht VB. :D
‮pb aktuel 6.2 windoof aktuell und sowas von 10
Ich hab Tinnitus im Auge. Ich seh nur Pfeifen.
Benutzeravatar
Eric
Beiträge: 303
Registriert: 05.09.2004 09:50
Wohnort: Göttingen

Beitrag von Eric »

Ich hab eine noch etwas schnellere Variante gebastelt: (bei mir etwa 3*so schnell wie Variante 1)

Code: Alles auswählen

;Variante 3
!mov eax,[v_MeinString$]
!cmp byte [eax],0 ;If MeinString$=""
!jne @f
;Hier kommt dann der Code rein, der ausgeführt wird, wenn MeinString$="" ist
!@@: ;EndIf
Ich hoffe mal, dass es mir PB nicht übel nimmt, wenn ich ihm ein Register entwende /:->

Ich kann auch noch ne Variante mit Else basteln, wird nur etwas umständlicher mit den anonymen Labels.

Noch ne kleine Anmerkung:
Durch die anonymen Labels lassen sich die dinger nicht ohne weiteres verschachteln, man müsste also das @@ und das @f durch etwas anderes ersetzen.
El_Choni_work: cant't you just spit the binary data to sqlite, as you would spit a hamster into a microwave oven?
* Fangles falls off the chair laughing
Bild
Benutzeravatar
Deeem2031
Beiträge: 1232
Registriert: 29.08.2004 00:16
Wohnort: Vorm Computer
Kontaktdaten:

Beitrag von Deeem2031 »

bobobo hat geschrieben:Es ist mir irgendwie leicht reinlaufend, dass ne Funktion irgendwie lahmer ist als ne direkte Zuweisung. Ich fahr doch auch nicht von Bielefeld nach Brackwede über Berlin. Bin aber auch nicht VB. :D
If sDummy$="" generiert auch einen Procedureaufruf (SYS_StringEqual) und da SYS_StringEqual und PB_Len den Stack nicht benutzen wird es am Aufruf nicht liegen. Es liegt allein daran das PB_Len nicht so gut optimiert wie SYS_StringEqual ist.

[Edit] Ich bin davon ausgegangen das der String leer ist, ist er nicht leer ist SYS_StringEqual in jedem Fall schneller, da PB_Len den ganzen String durchgehen muss, SYS_StringEqual aber nur das erste Byte vergleichen muss.
Bild
[url=irc://irc.freenode.org/##purebasic.de]irc://irc.freenode.org/##purebasic.de[/url]
Benutzeravatar
Sylvia
verheiratet<br>1. PureGolf-Gewinner
Beiträge: 487
Registriert: 29.08.2004 09:42
Wohnort: Old Europe

Beitrag von Sylvia »

Anstatt

Code: Alles auswählen

If sDummy$=""
sollte man lieber nur

Code: Alles auswählen

If sDummy$
als Umkehrabfrage schreiben (ca.3x schneller), sofern es der Übersichtlich- und
Verständlichkeit des Codes nicht abträglich ist


Allerdings ist

Code: Alles auswählen

If Len(sDummy$)=0
statt diese Umkehrvariante

Code: Alles auswählen

If Len(sDummy$)
kaum messbar langsamer, weil keine echte Stringbehandlung erfolgt
Basic Pur = PureBasic
Benutzeravatar
Batze
Beiträge: 1492
Registriert: 03.06.2005 21:58
Wohnort: Berlin
Kontaktdaten:

Beitrag von Batze »

Ich würde auch sagen

Code: Alles auswählen

If String$
Denn schließlich ist dann nur die Adresse auszulesen, die bei Leerstrings immer 0 ist.
Hier sind meine Codes (aber die Seite geht gerade nicht):
http://www.basicpure.de.vu
Benutzeravatar
Deeem2031
Beiträge: 1232
Registriert: 29.08.2004 00:16
Wohnort: Vorm Computer
Kontaktdaten:

Beitrag von Deeem2031 »

Batze hat geschrieben:Ich würde auch sagen

Code: Alles auswählen

If String$
Denn schließlich ist dann nur die Adresse auszulesen, die bei Leerstrings immer 0 ist.
Das meinst du doch nicht ernst oder? Ein NullString hat doch keinen NullPointer..
Bild
[url=irc://irc.freenode.org/##purebasic.de]irc://irc.freenode.org/##purebasic.de[/url]
Benutzeravatar
Batze
Beiträge: 1492
Registriert: 03.06.2005 21:58
Wohnort: Berlin
Kontaktdaten:

Beitrag von Batze »

Oh, das hab ich ja wirklich so geschrieben. :shock: :oops: :freak:
Ich meinte eigentlich nicht das die Adresse 0 ist sondern der Byte-Wert den man an der Adresse auslesen kann.
Ich denke - oder hoffe zumindest - dass PureBasic dann nur das eine Byte ausliest.
Hier sind meine Codes (aber die Seite geht gerade nicht):
http://www.basicpure.de.vu
Benutzeravatar
hardfalcon
Beiträge: 3447
Registriert: 29.08.2004 20:46

Beitrag von hardfalcon »

ICh hab bisher sowieso immer Sylvias Methode benutzt. (Ich wusste zwar nicht, dass sie schneller ist, aber es ist immerhin weniger zu tippen, und ich bin halt ein fauler Sack... :mrgreen: )
Mich würde mal interessieren, was schneller ist: If - ElseIf - Else - EndIf oder Select - Case - Default - EndSelect ? Aber da ich ein fauler Sack bin, kann ich mich grade nicht dazu durchringen das zu testen. Ich vermute mal, beides ist gleich schnell, sprich es wird der gleiche ASM-Code dafür generiert, es wird nur unter PB anders geschrieben... :lol:
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
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

Beitrag von NicTheQuick »

Ich denke, dass es anders ist.

Bei ElseIf kann man wieder eine ganz andere Bedingung angeben wie bei Select.
Bei Select wird der zu überprüfende Wert sicherlich nur einmal in ein Register geschoben und dann mit jedem Wert hinter Case verglichen bis ein Treffer gefunden wurde.
Hinter ElseIf kann man jedesmal zwei andere Variablen, Konstanten oder was weiß ich miteinander vergleichen. Und ich denke, dass PureBasic dahingehend noch nicht so weit optimiert.

Aber da ich mich mit ASM nicht gerne auseinandersetze, kann das gerne mal jemand anderes testen.
Antworten