Autor Beitrag
baka0815
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 489
Erhaltene Danke: 14

Win 10, Win 8, Debian GNU/Linux
Delphi 10.1 Berlin, Java, C#
BeitragVerfasst: Mo 14.04.08 15:38 
Ich experimentiere gerade etwas mit Delphi und Funktionen herum und habe in einer Bibliothek folgendes gefunden:

ausblenden 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:
ausblenden 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();

  // Liste füllen
  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:
ausblenden 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 user profile iconChristian S.: Code- durch Delphi-Tags ersetzt
jakobwenzel
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1889
Erhaltene Danke: 1

XP home, ubuntu
BDS 2006 Prof
BeitragVerfasst: 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

_________________
I thought what I'd do was, I'd pretend I was one of those deaf-mutes.
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8554
Erhaltene Danke: 480

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: 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:

_________________
We are, we were and will not be.
baka0815 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 489
Erhaltene Danke: 14

Win 10, Win 8, Debian GNU/Linux
Delphi 10.1 Berlin, Java, C#
BeitragVerfasst: 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.