Lass das ganze doch mal unter Delphi 1, 2, 3, 4, 5, 6, 7 und 2005 laufen. Dann wirst schon sehen, warum die das so gemacht haben. Tipp: Ab Delphi 2006 wird der FastMM4 als Standard Speichermanager eingesetzt.
Der FastMM ist fast nicht zu schlagen. Aber ein paar mickrige Millisekunden habe ich dann doch noch herausschlagen können. Die lassen sich aber nicht mittels GetTickCount ermitteln.
Delphi-Quellcode:
Function V2(s: TStringList): Integer;
Var
l, i, j, n: Integer;
z: PChar;
x: String;
Arr: array of record
Data: PChar;
Len: Integer;
end;
Begin
n := 0;
SetLength(Arr, s.Count);
For i := 0 To s.count - 1 Do
begin
Arr[i].Data := PChar(s[i]); // nur einmal in s.Get(i) wird LStrAsg ausgeführt => 3x LOCK
Arr[i].Len := Length(PString(@Arr[i].Data)^);
inc(n, Arr[i].Len);
end;
SetLength(x, n);
j := 0; // PChar startet bei 0
For i := 0 To High(Arr) Do Begin
z := Arr[i].Data;
l := Arr[i].Len;
Move(z^, PChar(PChar(Pointer(x)) + j)^, l * SizeOf(Char)); // kein UniqueString aufrufen
inc(j, l);
End;
Result := Length (x);
End;
procedure TForm1.btClick(Sender: TObject);
Var
s: TStringList;
i : IntegeR;
t0 : Cardinal;
z0: Int64;
z1: Int64;
Freq: Int64;
begin
QueryPerformanceFrequency(Freq);
s := TStringlist.Create;
try
for i:=1 to 1000000 do s.add(IntToStr(i));
QueryPerformanceCounter(z0);
v1(s);
QueryPerformanceCounter(z1);
Memo.Lines.Add('Stringkonkatenation: '+FloatToStr((z1 - z0) / Freq));
QueryPerformanceCounter(z0);
v2(s);
QueryPerformanceCounter(z1);
Memo.Lines.Add('Direktes Einkopieren: '+FloatToStr((z1 - z0) / Freq));
finally
s.free;
end;
end;
Stringkonkatenation: 0,07990568633723
Direktes Einkopieren: 0,072708333042328