Laufzeitmessung der Codeausführung [Gelöst]

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
MmVisual
Beiträge: 1470
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Laufzeitmessung der Codeausführung [Gelöst]

Beitrag von MmVisual »

Hallo,

Ich möchte gerne meinen Code optimieren. Dazu muss ich erst einmal die großen Dinge raus finden die viel Zeit benötigen. Dazu habe ich mir diese Routinen geschrieben um die Zeiten auf zu zeichnen:

- Start der Messung
- Zwischenzeiten
- Ende der Messung, Ausgabe als String

Leider funtioniert "Now" nicht, während der Ausführung der Routine hat "Now" immer den gleichen Wert. "Now" wird wohl nicht fortlaufend vom System gelesen.
Gibt es etwas anderes um einigermaßen ms genau die Laufzeit erfassen zu können?

Vielen Dank für Ideen, VG Markus

Hier der Code:

Code: Alles auswählen

Var lstTMess: TList;
// Zeitmessungen
// Start der Messung
Procedure TMessStart();
Begin
  If Not Assigned(lstTMess) Then
    lstTMess := TList.Create
  Else lstTMess.Clear;
  TMessPoint(); // Zeitstempel Start Zeitpunkt
End;

// Messpunkt hinzufügen
Procedure TMessPoint();
Var dt: TDateTime;
    i: LongInt absolute dt;
Begin
  If Assigned(lstTMess) Then
  Begin
    dt := Now;
    lstTMess.Add(Pointer(PtrInt(i)));
  End;
End;

// Ende Messung, Ausgabe Zeitwerte
Function TMessEnd(): String;
Var dt: TDateTime;
    i: LongInt absolute dt;
    dtStart: TDateTime;
Begin
  Result := '';
  If Not Assigned(lstTMess) Then
    Exit;
  If lstTMess.Count = 0 Then
    Exit;
  TMessPoint();
  i := PtrInt(lstTMess.Items[0]);
  dtStart := dt;
  lstTMess.Delete(0);
  While lstTMess.Count > 0 Do
  Begin
    i := PtrInt(lstTMess.Items[0]);
    Result := Result + ';' + FormatDateTime('[s]:zzz', dt - dtStart);
    lstTMess.Delete(0);
  End;
  If Result <> '' Then
    Delete(Result, 1, 1);
  FreeAndNil(lstTMess);
End; 
Zuletzt geändert von MmVisual am Mo 22. Jan 2024, 13:16, insgesamt 1-mal geändert.
EleLa - Elektronik Lagerverwaltung - www.elela.de

Benutzeravatar
theo
Beiträge: 10500
Registriert: Mo 11. Sep 2006, 19:01

Re: Laufzeitmessung der Codeausführung

Beitrag von theo »

MmVisual hat geschrieben:
Mo 22. Jan 2024, 12:35
Leider funtioniert "Now" nicht, während der Ausführung der Routine hat "Now" immer den gleichen Wert. "Now" wird wohl nicht fortlaufend vom System gelesen.
Gibt es etwas anderes um einigermaßen ms genau die Laufzeit erfassen zu können?
https://www.freepascal.org/docs-html/rt ... unt64.html

Code: Alles auswählen

var tick:Int64;
begin
  tick:=GetTickCount64;
  sleep(10);
  writeln(GetTickCount64-tick,' ms');
end;    

MmVisual
Beiträge: 1470
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Laufzeitmessung der Codeausführung

Beitrag von MmVisual »

Perfekt, Danke!
EleLa - Elektronik Lagerverwaltung - www.elela.de

siro
Beiträge: 732
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Laufzeitmessung der Codeausführung [Gelöst]

Beitrag von siro »

Wenn Du unter Windows unterwegs bist, gibt es eine wesentlich genauere Zeitmessung:

Code: Alles auswählen

var freq,tStart,tStop:Int64;
var t:Single;

procedure TForm1.FormCreate(Sender: TObject);
begin
  QueryPerformanceFrequency(freq);

  QueryPerformanceCounter(tStart);
  Sleep(1000);
  QueryPerformanceCounter(tStop);

  t:=(tStop-tStart) / freq;      // in Sekunden umrechnen
  caption:=FloatToStr(t);
end;                 
QueryPerformanceFrequency
braucht nur einmal aufgerufen werden, am besten bei Form.create
und liefert die Auflösung des Zeitgebers.
Bei mir kommt da 10.000.000 raus, was 100 Nanosekunden entspricht.
!!! Es wird die Unit "Windows" zusätzlich benötigt.

Wann läuft er über bei 64 Bit ???
Int64 hat 64 Bit
also einen Maxwert von 18.446.744.073.709.551.616 ohne Vorzeichen

multipliziert mit 100 Nano Sekunden sind das
1.844.674.407.370 Sekunden
30.744.573.456 Minuten
512.409.557 Stunden
21.350.398 Tage
58.494 Jahre
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

MmVisual
Beiträge: 1470
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Laufzeitmessung der Codeausführung [Gelöst]

Beitrag von MmVisual »

So kleine Zeiteinheiten sind mir unwichtig, mir ging es hauptsächlich im die Zeitfresser, die gleich mal 500ms und länger benötigen.
Wichtiger ist es dass die Funktion ebenfalls unter Linux geht, da ich damit auch progge.

Ein "TComboBox.Items.AddObject" in einer Schleife um die Liste zu füllen ist z.B. so ein Problem. Das braucht ewig lang.
Nun habe ich es umgebaut und fülle erst einmal ein TStringList, anschließend TComboBox.Items.Assign(TStringList), das geht deutlich schneller.

Vorher 2 Comboboxen gefüllt: 430ms
Nachher erst einne StringList gefüllt und dann erst den 2 Combos zugewiesen: 150ms

Ich vermute mal dass wegen jedem einzelnen Add in diese Stringliste jedes mal separat Speicher angefordert wird. Das kostet natürlich sehr viel Zeit. Wenn man nur jedes 10-te Anfordern würden und gleich für 10 Plätze wäre das effizienter. Denn RAM hat man in der Regel genügend.
EleLa - Elektronik Lagerverwaltung - www.elela.de

Mathias
Beiträge: 6209
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Laufzeitmessung der Codeausführung

Beitrag von Mathias »

theo hat geschrieben:
Mo 22. Jan 2024, 12:42
MmVisual hat geschrieben:
Mo 22. Jan 2024, 12:35
Leider funtioniert "Now" nicht, während der Ausführung der Routine hat "Now" immer den gleichen Wert. "Now" wird wohl nicht fortlaufend vom System gelesen.
Gibt es etwas anderes um einigermaßen ms genau die Laufzeit erfassen zu können?
https://www.freepascal.org/docs-html/rt ... unt64.html

Code: Alles auswählen

var tick:Int64;
begin
  tick:=GetTickCount64;
  sleep(10);
  writeln(GetTickCount64-tick,' ms');
end;    
Den kannte ich nicht, ich habe mich jetzt immer mit now rumgeschlagen. :oops:
Ich wusste doch, es müsste auch etwas mit Ganzzahlen geben.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

MmVisual
Beiträge: 1470
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Laufzeitmessung der Codeausführung [Gelöst]

Beitrag von MmVisual »

Hier mal noch mein Code:

Code: Alles auswählen

Var lstTMess: TList;

// Zeitmessungen
// Start der Messung
Procedure TMessStart();
Begin
  If Not Assigned(lstTMess) Then
    lstTMess := TList.Create
  Else lstTMess.Clear;
  lstTMess.Add(Pointer(PtrInt(GetTickCount64()))); // Zeitstempel Start Zeitpunkt setzen
End;

// Messpunkt hinzufügen
Procedure TMessPoint();
Begin
  If Assigned(lstTMess) Then
    lstTMess.Add(Pointer(PtrInt(GetTickCount64())));
End;

// Ende Messung, Ausgabe Zeitwerte
Function TMessEnd(): String;
Var i, iStart: LongInt;
Begin
  Result := '';
  If Not Assigned(lstTMess) Then Exit;
  lstTMess.Add(Pointer(PtrInt(GetTickCount64())));
  iStart := PtrInt(lstTMess.Items[0]);
  lstTMess.Delete(0);
  While lstTMess.Count > 0 Do
  Begin
    i := PtrInt(lstTMess.Items[0]);
    Result := Result + ';' + (i - iStart).ToString;
    lstTMess.Delete(0);
  End;
  If Result <> '' Then Delete(Result, 1, 1);
  FreeAndNil(lstTMess);
End;  
EleLa - Elektronik Lagerverwaltung - www.elela.de

wp_xyz
Beiträge: 4893
Registriert: Fr 8. Apr 2011, 09:01

Re: Laufzeitmessung der Codeausführung [Gelöst]

Beitrag von wp_xyz »

MmVisual hat geschrieben:
Mo 22. Jan 2024, 17:08
Ein "TComboBox.Items.AddObject" in einer Schleife um die Liste zu füllen ist z.B. so ein Problem. Das braucht ewig lang.
Nun habe ich es umgebaut und fülle erst einmal ein TStringList, anschließend TComboBox.Items.Assign(TStringList), das geht deutlich schneller.

Vorher 2 Comboboxen gefüllt: 430ms
Nachher erst einne StringList gefüllt und dann erst den 2 Combos zugewiesen: 150ms

Ich vermute mal dass wegen jedem einzelnen Add in diese Stringliste jedes mal separat Speicher angefordert wird. Das kostet natürlich sehr viel Zeit. Wenn man nur jedes 10-te Anfordern würden und gleich für 10 Plätze wäre das effizienter. Denn RAM hat man in der Regel genügend.
Hast du das Füllen der Combobox.Items in einen Combobox.Items.BeginUpate/.EndUpdate-Block gesetzt? Damit wird's gleich schneller, weil nach jedem hinzugefügten Item kein Neuzeichnen getriggert wird.

MmVisual
Beiträge: 1470
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Laufzeitmessung der Codeausführung [Gelöst]

Beitrag von MmVisual »

.... .Items.BeginUpate kannte ich bisher noch nicht. Ich dachte das BeginUpdate gibt es immer vom Control und nicht von den Items.

Vielen Dank für den Tipp.
EleLa - Elektronik Lagerverwaltung - www.elela.de

Antworten