Funktion um ein einzelnes Zeichen zu suchen:
Ich habe bisschen gelesen und folgende Behauptungen gefunden:
- Inline geht schneller
- Pointer sind schneller
- PoxEx ist langsamer
- Zeichen Zählen durch Schleife geht am schnellsten
Das konnte ich nicht glauben. Und das wollte ich nun überprüfen.
Delphi-Quellcode:
function CountChar(const S: string; C: Char): Integer;
var
i: Integer;
begin
Result := 0;
for i := 1 to Length(S) do
if S[i] = C then
Inc(Result);
end;
function CountChar2(const S: string; C: Char): Integer; inline;
var
P: PChar;
begin
Result := 0;
P := PChar(S);
while P^ <> #0 do
begin
if P^ = C then
Inc(Result);
Inc(P);
end;
end;
function CountChar3(const S: string; C: Char): Integer; inline;
var
i: Integer;
begin
Result := 0;
for i := 1 to Length(S) do
if S[i] = C then
Inc(Result);
end;
function CountChar4(const S: string; C: Char): Integer;
var
P: PChar;
begin
Result := 0;
P := PChar(S);
while P^ <> #0 do
begin
if P^ = C then
Inc(Result);
Inc(P);
end;
end;
function CountChar5(const S: string; C: Char): Integer;
var
StartPos: Integer;
begin
Result := 0;
StartPos := 1;
while StartPos <= Length(S) do
begin
StartPos := PosEx(C, S, StartPos);
if StartPos = 0 then
Break;
Inc(Result);
Inc(StartPos);
end;
end;
Ich habe nun verschiedene Sachen überprüft. Große Dateien, kleine Dateien, mit Zahlen, Buchstaben, usw.
Das ist mein Ergebnis:
Grundsätzlich, egal welche Variante man wählt, spielt sich die Ausführungszeit nur im Millisekundenbereich (< 999 ms) ab. Für eine einmalige oder wenige Ausführungen und kleinen Datenmengen (also unter 100 MB), ist es egal für was man sich entscheidet. In allen meinen Tests war die Ausführungszeit unter 1 Sekunde.
Ergebnis:
In >90 % der Fällen war die Variante mit PosEx (Countchar5) am schnellsten. In den meisten Fällen doppelt so schnell, wie die langsamste Variante. Bei wenigen Treffern, teilweise 6x schneller als die langsamste Variante.
Die Variante jedes einzelne Zeichen mit While (countchar) zu überprüfen, war praktisch durchgehend das langsamste.
Pointer war schneller als die Variante ohne, aber langsamer als PosEx und war in der Regel im Mittelfeld.
"Inline" machte keinen Unterschied.
Trotzdem noch eine Anmerkung. Es kommt auch ein bisschen auf den Inhalt des durchsuchenden an. PosEx wird die langsamste Variante wenn der Text zu 100% aus dem gesuchten Zeichen besteht (das halte ich in der Praxis für unwahrscheinlich). In meinen Tests war dann die Pointer Variante die schnellste (und PosEx ca. 5x langsamer).
Besteht die Hälfte des Textes aus dem gesuchten Zeichen, ist PosEx immer noch die langsamste (ca. 2x so langsam wie der schnellste), und die Pointer Variante ist die schnellste.
Besteht ein Drittel des Textes aus dem gesuchten Zeichen, ist PosEx immer noch die langsamste (ca. 1,5x langsamer als der schnellste, die Pointer Variante)
Nach meinen Tests ist PosEx die schnellste Variante, wenn das gesuchte Zeichen weniger als 20% des Textes vorkommt (was immer noch viel ist). Wobei es auch auf die Textzusammensetzung ankommen kann, und auch auf die Größe des zu durchsuchenden Textes.
Bei kurzen Texten und sehr kurzen Texten (z.B. 100 KB), war PosEx die langsamste und die Schleifenvariante die schnellste. Dann sind die anderen Varianten aber nur 0,01-2% langsamer - also wie schon oben beschrieben, vernachlässigbar. Zumal wir uns bei den kurzen Texten dann schon bei wenigen ms (< 10 ms) und µs bewegen.
Deswegen würde ich behaupten, mit der PosEx Variante fährt man am besten. Und im Zweifel mit der Pointer Variante. Nicht aber die Schleifenvariante.