Registriert seit: 17. Nov 2005
Ort: Hamburg
1.077 Beiträge
Delphi XE2 Professional
|
AW: Alternative zu PosEx
1. Dez 2024, 09:39
Das anfängliche "SetLength()" bewirkt weniger als erwartet, dafür bingt "inline" deutlich mehr Zeitersparnis:
Delphi-Quellcode:
function MyStrPosEx(const SearchFor, SearchIn: string; Estimated: Integer = 0): TIntegerDynArray;
function Search(const SearchFor, SearchIn: string; var Index: Integer): Boolean; inline;
begin
Index := Pos(SearchFor, SearchIn, Index + 1);
Result := (Index > 0);
end;
begin
SetLength(Result, Estimated);
var Count: Integer := 0;
var Index: Integer := 0;
while Search(SearchFor, SearchIn, Index) do
begin
Inc(Count);
{Array vergrößern braucht viel Zeit, deshalb gleich etwas mehr Platz reservieren}
if Estimated < Count then
begin
Estimated := Count * 2;
SetLength(Result, Estimated);
end;
Result[Count - 1] := Index;
end;
SetLength(Result, Count);
end;
Code:
StrPosEx('7', sRandomString, Positions)
0:00:00.102
Result := MyStrPosEx('7', sRandomString, 0)
0:00:00.168
Result := MyStrPosEx('7', sRandomString, 10000000)
0:00:00.157
Sorry, aber ich kann die Ergebnisse Deiner Zeitmessungen nicht nachvollziehen.
Ich habe SRandomString auf eine Länge von 80 Mio gesetzt und mit Zufallszeichen im Bereich "0".."9" gefüllt.
In Deiner Funktion "Search" habe ich "Pos" durch "PosEx" (aus System.StrUtils) ersetzt, weil bei mir (Delphi XE2) "Pos" keinen Offset unterstützt.
Ergebnisse im Anhang.
Meine Test-Prozedur:
Delphi-Quellcode:
PROCEDURE TMain.Test;
resourcestring
sFmt='F:%S, R:%D, T:%S ms';
var
I,R1,R2,R3:Integer;
T1,T2,T3:Int64;
DT:TDateTime;
S1,S2,SRandomString:String;
Positions:TIntegerDynArray;
begin
SetLength(SRandomString,80000000);
for I:=1 to Length(SRandomString) do
SRandomString[I]:=Char(Random(10)+Ord('0'));
// Zeitmessung auf Basis TimeStampCounter
// StrPosEx
T1:=TimeStamp;
SetLength(Positions,8100000);
R1:=StrPosEx('7',sRandomString,Positions);
SetLength(Positions,R1);
T1:=TimeStamp-T1;
// MyStrPosEx mit Esrimated=0
Positions:=Nil;
T2:=TimeStamp;
Positions:=MyStrPosEx('7',sRandomString,0);
R2:=Length(Positions);
T2:=TimeStamp-T2;
// MyStrPosEx mit Esrimated=8100000
Positions:=Nil;
T3:=TimeStamp;
Positions:=MyStrPosEx('7',sRandomString,8100000);
R3:=Length(Positions);
T3:=TimeStamp-T3;
S1:='Zeitmessung auf Basis TimeStampCounter'#13+
Format(sFmt,['StrPosEx',R1,TicksToStr(T1)])+#13+
Format(sFmt,['MyStrPosEx 0',R2,TicksToStr(T2)])+#13+
Format(sFmt,['MyStrPosEx 8100000',R3,TicksToStr(T3)]);
// Zeitmessung auf Basis TDateTime
// StrPosEx
DT:=Now;
SetLength(Positions,8100000);
R1:=StrPosEx('7',sRandomString,Positions);
SetLength(Positions,R1);
T1:=MilliSecondsBetween(DT,Now);
// MyStrPosEx mit Esrimated=0
Positions:=Nil;
DT:=Now;
Positions:=MyStrPosEx('7',sRandomString,0);
R2:=Length(Positions);
T2:=MilliSecondsBetween(DT,Now);
// MyStrPosEx mit Esrimated=8100000
Positions:=Nil;
DT:=Now;
Positions:=MyStrPosEx('7',sRandomString,8100000);
R3:=Length(Positions);
T3:=MilliSecondsBetween(DT,Now);
S2:='Zeitmessung auf Basis TDateTime'#13+
Format(sFmt,['StrPosEx',R1,IntToStr(T1)])+#13+
Format(sFmt,['MyStrPosEx 0',R2,IntToStr(T2)])+#13+
Format(sFmt,['MyStrPosEx 8100000',R3,IntToStr(T3)]);
ShowMessage(S1+#13#13+S2);
end;
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
|