AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

VAR CONST OUT und Co. ... warum?

Ein Thema von himitsu · begonnen am 29. Apr 2009
Antwort Antwort
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.136 Beiträge
 
Delphi 12 Athens
 
#1

VAR CONST OUT und Co. ... warum?

  Alt 29. Apr 2009, 23:24
da es ja immer öfters mal vorkommt, daß gefragt wird warum es oftmals besser ist ein CONST anzugeben

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 )

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 )
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
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:48 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz