da es ja immer öfters mal vorkommt, daß gefragt wird warum es oftmals besser ist ein CONST anzugeben
![](styles/elise/misc/quote_24x24.png)
Zitat von
himitsu:
wenn die Variablen eh nicht verändert werden sollen, wozu sie veränderbar machen?
(also Prozedurintern)
gut, bei Strings gibt es die Referenzzählung, aber nicht immer (vorallem nicht bei WideString)
und bei Records und auch allem über 32 Bit wird ohne das Const erst eine Kopie des Parameters angelegt, worin die Prozeduinternen änderungen stattfinden können.
übergib mal z.B. ein rießiges Static-Array, einen großen Record oder einen langen WideString ... diese müssen erst kopiert und am Ende wieder freigegeben werden.
und auch bei kleinen Strukturen müßte das erst von Delphi gemacht werden, selbst wenn es unnötig wäre.
CONST (könnte man auch als IN), VAR, OUT und (nichts) gibt es ja nicht umsonst zur Auswahl
und Const bzw. Var wird bei "größeren" Strukturen dann einfach als Zeiger auf die Originaldaten umgesetzt und läuft nicht über 'ne "Kopie".
(kleine Ausnahmen bilden Objekte, welche "nur" Zeiger sind,
sowie Strings bzw. DynArrays, welche eine Referenzzählung besitzen)
aus
http://www.delphipraxis.net/internal...031883#1031883
Da die Meisten eh nicht sehen, was hinter den Kulissen alles von Delphi wann gemacht wird, hab ich es einfach mal über eine Laufzeitmessung dargestellt (je mehr gemacht wird, umso länger dauert es ja bekanntlich
![Nerd](images/smilies/nerd.gif)
)
Es wäre es schwer hier alles aufzuzeigen, was wann gemacht wird, da es von den Datentypen und auch noch von der Aufrufkonvention abhängig ist, was wie wo gemacht wird ... außerdem ist es ja nur wichtig zuwissen daß etwas gemacht wird und das wie ist hierbei mal völlig egal.
hier ein kleiner Testcode, welcher
- ein wirklich großes 10-MB-Array
- einen String
- einen Record
- und 'nen Int64 (auch wenn da die Aufrufconvention eigenartig ist
![Confused](images/smilies/icon_confused.gif)
)
testet.
Delphi-Quellcode:
{$MAXSTACKSIZE 25000000} // ist sonst nur 1 MB
// und das 10-MB-Array muß ja dort 2-mal reinpassen (doppelt, für die Kopie ohne Const/Var)
Type TArray = Array[1..10*1024*1024] of Byte;
TDynArray = Array of Byte;
Procedure TestProcA(Arr: TArray);
Begin If Arr[2] = 2 Then ; End;
Procedure TestProcAC(Const Arr: TArray);
Begin If Arr[2] = 2 Then ; End;
Procedure TestProcAV(Var Arr: TArray);
Begin If Arr[2] = 2 Then ; End;
Procedure TestProcD(Arr: TDynArray);
Begin If Arr[2] = 2 Then ; End;
Procedure TestProcDC(Const Arr: TDynArray);
Begin If Arr[2] = 2 Then ; End;
Procedure TestProcDV(Var Arr: TDynArray);
Begin If Arr[2] = 2 Then ; End;
Procedure TestProcS(S: String);
Begin If S = '' Then ; End;
Procedure TestProcSC(Const S: String);
Begin If S = '' Then ; End;
Procedure TestProcR(R: TRect);
Begin If R.Left = 0 Then ; End;
Procedure TestProcRC(Const R: TRect);
Begin If R.Left = 0 Then ; End;
// Integer drin, damit der der Int64 nicht in den Registern landet (AntiParameterOptimierung)
Procedure TestProcI(i: Integer; i2: UInt64);
Begin If i2 = 0 Then ; End;
// irgendwie bin ich grad zu blöd und Int64 wir dennoch in die Register/den Stack geladen
Procedure TestProcIC(i: Integer; {Const}Var i2: UInt64);
Begin If i2 = 0 Then ; End;
Procedure TForm1.Button1Click(Sender: TObject);
Var Ts, Te: Int64;
Arr: TArray;
DynArr: TDynArray;
S: String;
R: TRect;
F: Double;
i2: UInt64;
i: Integer;
C: LongWord;
Begin
Memo1.Lines.Clear;
Memo1.Font.Name := 'Courier New';
C := GetTickCount;
// CPU hochfahren, falls sie dynamisch getaktet ist
QueryPerformanceCounter(Ts);
For i := 0 to 500000000 do i2 := i;
QueryPerformanceCounter(Te);
Memo1.Lines.Add(Format('spin up: %11.0n ticks', [(Te - Ts) / 1]));
Memo1.Lines.Add('');
QueryPerformanceCounter(Ts);
For i := 0 to 1000 do Begin
Arr[2] := i;
TestProcA(Arr);
End;
QueryPerformanceCounter(Te);
Memo1.Lines.Add(Format('Array: %11.0n ticks', [(Te - Ts) / 1]));
QueryPerformanceCounter(Ts);
For i := 0 to 1000 do Begin
Arr[2] := i;
TestProcAC(Arr);
End;
QueryPerformanceCounter(Te);
Memo1.Lines.Add(Format('Array-Const: %11.0n ticks', [(Te - Ts) / 1]));
QueryPerformanceCounter(Ts);
For i := 0 to 1000 do Begin
Arr[2] := i;
TestProcAV(Arr);
End;
QueryPerformanceCounter(Te);
Memo1.Lines.Add(Format('Array-Var: %11.0n ticks', [(Te - Ts) / 1]));
Memo1.Lines.Add('');
SetLength(DynArr, 10*1024*1024);
QueryPerformanceCounter(Ts);
For i := 0 to 1000 do Begin
DynArr[2] := i;
TestProcD(DynArr);
End;
QueryPerformanceCounter(Te);
Memo1.Lines.Add(Format('DynArray: %11.0n ticks', [(Te - Ts) / 1]));
QueryPerformanceCounter(Ts);
For i := 0 to 1000 do Begin
DynArr[2] := i;
TestProcDC(DynArr);
End;
QueryPerformanceCounter(Te);
Memo1.Lines.Add(Format('DynArray-Const: %11.0n ticks', [(Te - Ts) / 1]));
QueryPerformanceCounter(Ts);
For i := 0 to 1000 do Begin
DynArr[2] := i;
TestProcDV(DynArr);
End;
QueryPerformanceCounter(Te);
Memo1.Lines.Add(Format('DynArray-Var: %11.0n ticks', [(Te - Ts) / 1]));
Memo1.Lines.Add('');
QueryPerformanceCounter(Ts);
For i := 0 to 100000 do TestProcS(S);
QueryPerformanceCounter(Te);
Memo1.Lines.Add(Format('String: %11.0n ticks', [(Te - Ts) / 1]));
QueryPerformanceCounter(Ts);
For i := 0 to 100000 do TestProcSC(S);
QueryPerformanceCounter(Te);
Memo1.Lines.Add(Format('String-Const: %11.0n ticks', [(Te - Ts) / 1]));
Memo1.Lines.Add('');
QueryPerformanceCounter(Ts);
For i := 0 to 100000 do TestProcR(R);
QueryPerformanceCounter(Te);
Memo1.Lines.Add(Format('TRect: %11.0n ticks', [(Te - Ts) / 1]));
QueryPerformanceCounter(Ts);
For i := 0 to 100000 do TestProcRC(R);
QueryPerformanceCounter(Te);
Memo1.Lines.Add(Format('TRect-Const: %11.0n ticks', [(Te - Ts) / 1]));
Memo1.Lines.Add('');
QueryPerformanceCounter(Ts);
For i := 0 to 200000 do TestProcI(i, i2);
QueryPerformanceCounter(Te);
Memo1.Lines.Add(Format('Int64: %11.0n ticks', [(Te - Ts) / 1]));
QueryPerformanceCounter(Ts);
For i := 0 to 200000 do TestProcIC(i, i2);
QueryPerformanceCounter(Te);
Memo1.Lines.Add(Format('Int64-{Const}Var: %11.0n ticks', [(Te - Ts) / 1]));
Memo1.Lines.Add('');
Memo1.Lines.Add(Format('end (%n sec)', [(GetTickCount - C) / 1000]));
End;
raus kommt dann z.B. sowas (D7)
Code:
spin up: 2.259.813 ticks
Array: 27.141.695 ticks
Array-Const: 13 ticks
Array-Var: 16 ticks
DynArray: 117 ticks
DynArray-Const: 16 ticks
DynArray-Var: 16 ticks
String: 12.047 ticks
String-Const: 932 ticks
TRect: 2.387 ticks
TRect-Const: 799 ticks
Int64: 2.188 ticks
Int64-{Const}Var: 1.879 ticks
end (8,24 sec)
[edits] was man noch so alles anders machen kann