Entwickler-Ecke
Sonstiges (Delphi) - Geschwindigkeit TStringList
baka0815 - Mo 14.04.08 15:38
Titel: Geschwindigkeit TStringList
Ich experimentiere gerade etwas mit Delphi und Funktionen herum und habe in einer Bibliothek folgendes gefunden:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| function SearchInList(text : string; list : TStrings): Integer; var j : Integer; begin Result := -1; for j := 0 to list.count - 1 do IF POS (text, list[j]) = 1 then begin Result := j; Break; end; end; |
Was die Funktion macht, ist recht schnell klar: sucht nach dem String "text" in der übergebenen TStrings-Liste.
Ich habe die Schleife extra mit "downto" deklariert, damit die Funktion wirklich immer bis zum Ende durchlaufen muss.
Folgender Code-Ausschnitt soll zur Prüfung der Geschwindigkeit dienen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| (...) liste := TStringList.Create();
i2 := 50000; for i := 0 to i2 do begin liste.Add('String #' + IntToStr(i)); end;
QueryPerformanceFrequency(n1);
QueryPerformanceCounter(n2); for i := i2 downto 0 do begin SearchInList('String #' + IntToStr(i), liste); end; QueryPerformanceCounter(n3); diffA := (n3-n2) * 1000 div n1; (...) |
Für 50.000 Einträge braucht das Konstrukt ganze 70 Sekunden!
Nun hat die abstrakte Klasse TStrings aber eine indexOf()-Methode, die ich sofort getestet habe:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| QueryPerformanceCounter(n2); for i := i2 downto 0 do begin liste.IndexOf('String #' + IntToStr(i)); end; QueryPerformanceCounter(n3); diffA := (n3-n2) * 1000 div n1; |
Das dauert allein bei 20.000 Einträgen bereits 56 Sekunden, die Funktion von oben benötigt jedoch (nur) 11 Sekunden!
Kann mir jemand erklären, warum die eingebaute Methode indexOf so viel länger braucht?
Wenn ich statt der Klasse TStringList jedoch eine THashedStringList verwende, reden wir von 0,1 Sekunden bei 50.000 Sätzen, die ist also ausser Konkurrenz.
Moderiert von
Christian S.: Code- durch Delphi-Tags ersetzt
jakobwenzel - Mo 14.04.08 15:56
Die Funktion IndexOf verwendet intern nicht Pos zum vergleichen, sondern AnsiCompareText. Pos ist eigentlich auch inkorrekt, da der Suchtext bei deiner Pos-Version nur am Anfang des Eintrags stehen muss und auch durchaus kürzer sein kann. Bei AnsiCompareText muss jedoch alles komplett gleich sein.
AnsiCompareText braucht für 10000000 Aufrufe 2,14s, gegenüber 79ms bei Pos.
PS: Mitgelieferte VCL-Sourcen sind was tolles :P
Gausi - Mo 14.04.08 15:59
IndexOf sollte auch deutlich schneller sein, wenn die Eigenschaft sorted der Stringlist auf True steht. Den Unterschied zwischen 56 und 11 Sekunden könnte ich mir durch ein Nicht-Abbrechen von IndexOf beim ersten Treffer erkären - aber ich hab da den Source grade nicht parat :nixweiss:
baka0815 - Mo 14.04.08 16:09
Doch, er bricht ab (bin vorher nicht auf die Idee gekommen, selbst in die Sourcen zu gucken).
TStrings führt ein AnsiCompareText() aus mit dem übergebenen Wert und dem per Get() aus der Liste geholten.
TStringList führt indexOf() der Vaterklasse (also TStrings) aus, wenn die Liste nicht sortiert ist.
Wird die TStringList auf Sorted = True gesetzt, dauert das indexOf bei 20.000 EInträgen auch nur noch 0,068 Sekunden.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!