Moin moin zum Benchen hab ich für andere Beispiele das
GetTick von Agner Fog genommen. Es kommt kein Zeitwert raus aber ein Wert mit dem man arbeiten kann. Getestet mit VAR OUT CONST hab ich es selbst noch nicht aber bei Bedarf kann ich es Nachreichen.
...was nicht notwendig ist, denn man hat ja immer die GetTickCount-Routine von Windows. Diese ist in der
RTL schön gewrappt und abrufbar. Hab mir da so ein schönes stückchen Code gebastelt, das im grunde für fast alles anwendbar ist und mit dem ich für jede beliebige Routine ohne viel Anpassarbeit immer die Performance Ablesen kann. Das, auf diesen Fall zugeschnitten, sieht bei mir dann so aus:
Delphi-Quellcode:
const
amount = 1000000;
attempts = 50;
var
x,y: cardinal;
tickstart, tickfinish: cardinal;
allcounts: cardinal; s: String;
begin
allcounts := 0;
for x := 1 to attempts do
begin
y := 1;
tickstart := GetTickCount;
while y <= amount do
begin
Randomize;
SetLength(s, Random(255));
//entw Foo(s);
//oder FooC(s);
//oder FooV(s);
inc(y);
end;
tickfinish := GetTickCount;
allcounts := allcounts + tickfinish - tickstart;
end;
showmessage(inttostr((allcounts div attempts)));
end;
Ja, ich weiß, Code qualität und Formatierung zum Kotzen, aber darauf kommt es hier idF mal nicht an.
Was hier geschieht, kurz und Knackig: Es wird eine der drei Routinen 1000000 mal hintereinander aufgerufen und von diesen Aufrufen die insgesamte Zeit (Ticks) gemessen. Das ganze wird 50 mal ausgeführt, und das Endergebnis am Ende durch 50 geteilt. So hat man einen Durchschnittswert, der auf 50 Versuchen basiert, und die Zeit für 1000000 Aufrufe widergibt. Der String besitzt immer eine Zufallslänge zwischen 0 und 255, die vor jedem Funktionsaufruf neu ausgewürfelt wird.
Die Testroutinen waren für die Erste Versuchsreihe wie folgt deklariert:
Delphi-Quellcode:
procedure Foo(S: String);
begin
end;
procedure FooC(const S: String);
begin
end;
procedure FooV(var S: String);
begin
end;
Die Ergebnisse waren beeindruckend, wenn man es so beschreiben will:
- Für Foo(s): 77 Ticks je 1000000 Aufrufe im Schnitt
- Für FooC(s): 48 Ticks je 1000000 Aufrufe im Schnitt
- Für FooV(s): 48 Ticks je 1000000 Aufrufe im Schnitt
Nun habe ich Statt
Unicode-
Ansi-Strings genommen. Der Benchmark lief wie folgt ab:
- Für Foo(s): 74 Ticks je 1000000 Aufrufe im Schnitt
- Für FooC(s): 50 Ticks je 1000000 Aufrufe im Schnitt
- Für FooV(s): 50 Ticks je 1000000 Aufrufe im Schnitt
Bei ShortString, so dachte ich mir, könne man sogar noch mehr Performance herausholen. So testete ich dies ebenfalls:
- Für Foo(s): 64 Ticks je 1000000 Aufrufe im Schnitt
- Für FooC(s): 39 Ticks je 1000000 Aufrufe im Schnitt
- Für FooV(s): 39 Ticks je 1000000 Aufrufe im Schnitt
Es scheint, als dass in den meisten Fällen, die bei zufälligen Stringlängen generiert wurden, "const" und "var" sich identisch verhalten, oder zumindest eine identische Performance besitzen. Hervorstechen tut ganz klar Foo, und zwar im negativen Sinne.
Im allgemeinen kann man grob geschätzt sagen, dass sich mit "const" die Performance bei UnicodeStrings (um 37,7%), bei AnsiStrings (um 32,4%), sowie bei ShortStrings (um 39,1%) steigern lässt. Verallgemeinert lässt sich hier eine Tendenz von etwas über einem Drittel im Schnitt feststellen. Zwischen "var" und "const" konnte in dieser Testreihe kein merklicher Unterschied festgestellt werden. Ich gehe davon aus, dass dies nur bei genauerer bestrachtungsweise der String-Länge passieren kann. Darauf, das zu überprüfen, habe ich aber im Augenblick leider keinen Bock, weshalb die Fragestellung hier offen bleibt. Evtl kann ja jemand anderes hier aushelfen...?