![]() |
Gibt es einen schnelleren Stringvergleich als if S1 = S2
Sitz‘ grad mal wieder über einem meiner 88000 Parser. Dabei ist mal wieder bei mir die Frage aufgetaucht, ob es einen schnelleren Stringvergleich als if S1 = S2 gibt? Vermutlich nein, sonst wäre er in Delphi implementiert. Richtig?
|
AW: Gibt es einen schnelleren Stringvergleich als if S1 = S2
Zitat:
![]() Der Vergleich zweier Strings kann eventuell durch folgende Heuristik schneller werden. Vergleiche die Längen, dann das jeweils erste Zeichen und dann das jeweils letzte Zeichen. Nur wenn alle drei Vergleiche TRUE ergeben, vergleiche den Rest des Strings. Ich denke aber, die Compare-Routinen sind schon optimiert |
AW: Gibt es einen schnelleren Stringvergleich als if S1 = S2
Genau so macht es Delphi, Zeichen für Zeichen.
|
AW: Gibt es einen schnelleren Stringvergleich als if S1 = S2
Und bei AnsiCompareStr? AFAIK wird dort die API-Funktion CompareString mit den Spracheinstellungen des aktuellen Users aufgerufen, welche mit PChars arbeitet. Das dürfte schneller sein, kommt zumindest auf einen Versuch an.
|
AW: Gibt es einen schnelleren Stringvergleich als if S1 = S2
Zitat:
|
AW: Gibt es einen schnelleren Stringvergleich als if S1 = S2
Zitat:
Das ist (bis jetzt) am schnellsten:
Delphi-Quellcode:
function StrCompare(const S1, S2: string): boolean;
begin if Length(S1) <> Length(S2) then Result:= false else Result:= S1 = S2; end; |
AW: Gibt es einen schnelleren Stringvergleich als if S1 = S2
Es ist ein Unterschied ob man nur wissen muss ob 2 Strings gleich sind oder wie z.B. bei AnsiCompareStr ob ein String kleiner, grösser oder gleich ist.
Daher ist if
Delphi-Quellcode:
langsamer als
AnsiCompareStr(s1,s2)=0 then
Delphi-Quellcode:
.
if s1 = s2 then
Hier sollte man sprachlich besonders präzise sein; will man vergleichen oder auf Gleichheit prüfen?
Delphi-Quellcode:
Wenn man sich anschaut, wie ein AnsiString im Speicher liegt
function StrEquals(const s1,s2:string):Boolean; // prüft ob zwei strings gleich sind
function StrCompare(const s1,s2:string):Integer; // 0=beide gleich, 1=s1 ist grösser, -1=s1 ist kleiner ![]() dann muss man Folgendes tun: 1.) sind die beiden Zeiger s1 und s2 gleich? Falls ja: return(true) 2.) ist einer der beiden Zeiger = nil Falls ja: return(false) 3.) Längen der strings holen 4.) sind die Längen ungleich? Falls ja: return(false) 5.) Zeichen für Zeichen auf Gleichheit prüfen. Bei Abweichung return(false) 6.) return(true) Wenn man die Punkte 1. bis 6. in Assembler ausprogrammiert erhält man die max. mögliche Geschwindigkeit. Besonders bei 5. kann man z.B. durch schnellere CPU-Befehle SIMD, SSE,... noch einiges an Zeit rausholen. |
AW: Gibt es einen schnelleren Stringvergleich als if S1 = S2
Weil es mich auch interessiert hat, habe ich Furtbichlers Vorschlag getestet. Letztendlich dauert der Vergleich dann sogar länger, aber nur paar Millisekunden.
Hier das Beispiel zum überprüfen:
Delphi-Quellcode:
uses
DateUtils; procedure TForm1.Button1Click(Sender: TObject); var i, k, m, c, x: Integer; t1, t2: TTime; s, s1, s2: String; begin Screen.Cursor := crHourGlass; c := 0; Caption := ''; t1 := Now; x := 10000000; // 10 Mio. Durchläufe for i := 1 to x do begin k := Random(MaxInt); m := Random(MaxInt); s1 := IntToStr(k); //die Hälfte der Strings sind gleich if Odd(i) then s2 := IntToStr(k) else s2 := IntToStr(m); //Direkt - Beispiel 1 //if s1 = s2 then Inc(c); //Indirekt - Beispiel 2 if Length(s1) = Length(s2) then if s1[1] = s2[1] then if s1[Length(s1)] = s2[Length(s2)] then if s1 = s2 then Inc(c); end; t2 := Now; Caption := Format('Gleich: %d von %d; Millisek.: %d', [c, x, MilliSecondsBetween(t1, t2)]); Screen.Cursor := crDefault; end; |
AW: Gibt es einen schnelleren Stringvergleich als if S1 = S2
Ne Frage nebenbei (jz nicht nur dies hier betreffend, sondern auch etwas allgemeiner):
Delphi-Quellcode:
Ist folgende Variante nicht schneller? Oder optimiert das Delphi allgemein genauso?
if Length(s1) = Length(s2) then
if s1[1] = s2[1] then if s1[Length(s1)] = s2[Length(s2)] then if s1 = s2 then Inc(c);
Delphi-Quellcode:
Sry hab kB Delphi zu starten und zu disassemblieren. Vlt weiß es ja einer auf Anhieb.
len := Length(s1);
if len = Length(s2) then if s1[1] = s2[1] then if s1[len] = s2[len] then // hier! if s1 = s2 then Inc(c); |
AW: Gibt es einen schnelleren Stringvergleich als if S1 = S2
Nur etwas Statistik. Man sollte bedenken, dass auch der sonstige Code um die eigentlich Abfrage Zeit verbraucht. So werden 50 Mio. FOR Schleifen, abzüglich der IF Zeile oder Zeilen (je nach Beispiel) in meinem Rechner in 4820 Millisekunden abgewickelt.
Also 50. Mio Schleifen ohne IF Zeilen durchschnittlich in 4820 Millisekunden 50. Mio Schleifen mit einer IF Zeile (Bsp. 1) durchschnittlich in 5035 Millisekunden 50. Mio Schleifen mit vier IF Zeilen (Bsp. 2) durchschnittlich in 5060 Millisekunden 50. Mio Schleifen mit zwei IF Zeilen (Bsp. 3) durchschnittlich in 5020 Millisekunden
Delphi-Quellcode:
50. Mio Schleifen mit vier IF Zeilen (Aphtons Beispiel) durchschnittlich in 5035 Millisekunden
//Bsp. 3
if Length(s1) = Length(s2) then if s1 = s2 then Inc(c); Wie man sieht werden etwas 50. Mio Vergleiche in ca. 200 Millisek. durchgeführt. Das macht 4 Nanosekunden pro Vergleich. Ich würde sagen, das die Funktion optimiert ist. Die Unterschiede zwischen den Beispielen sind eher marginal. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:39 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz