Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Quelle hoher Prozessorauslastung ermitteln (https://www.delphipraxis.net/177081-quelle-hoher-prozessorauslastung-ermitteln.html)

Sven M. 15. Okt 2013 07:42

Quelle hoher Prozessorauslastung ermitteln
 
Moin zusammen,
folgende Situation:
Ich entwickle derzeit eine Software, die bestimmte Messwerte erfasst und daraufhin bestimmte Parameter regelt. Diese Software soll bis zu 2 Monate am Stück laufen. Nun habe ich allerdings das Problem, dass anfangs alles einwandfrei funktioniert, mit steigender Laufzeit jedoch immer längere Perioden auftreten, die den Prozessor zu 100% auslasten. Das geht soweit, dass das Programm irgendwann einfach nicht mehr reagiert. Ich tue mich nun leider momentan schwer, die Ursache dafür herauszufinden.

Gibt es irgendeine Art Tool, Klasse oder sonst was für 'nen kleinen Helfer, der mir sagt, in welcher Klasse und Funktion die große Auslastung begründet liegt? Oder bin ich auf mich allein gestellt?


Beste Grüße
Sven

Bernhard Geyer 15. Okt 2013 07:49

AW: Quelle hoher Prozessorauslastung ermitteln
 
Siehts du im Taskmanager welches Programm die 100% CPU verursacht?
Oder bist du dir sicher das es dein Programm ist?

jaenicke 15. Okt 2013 07:51

AW: Quelle hoher Prozessorauslastung ermitteln
 
Du kannst einerseits den Process Explorer verwenden, insbesondere in den Prozessdetails im Reiter Threads. Wenn du .dbg Debuginformationen bereitstellst, siehst du dort nicht nur in welchem Thread, sondern auch mit welchen Aufrufstacks im Moment Auslastung verursacht wird.

Andererseits kannst du, wenn du auf dem PC selbst debuggen kannst, Delphi dort starten und dich mit dem Prozess verbinden. Dann kannst du direkt dort debuggen.

Falls die Angabe deiner Delphiversion veraltet ist:
Mit aktuelleren Versionen kannst du auch per Remote Debugger aus der Ferne den Prozess debuggen. Zudem kannst du dort auch leicht die einzelnen Threads anschauen und kommst auch an die jeweilige Codestelle, an der der Thread gerade angehalten wurde.

Bernhard Geyer 15. Okt 2013 07:54

AW: Quelle hoher Prozessorauslastung ermitteln
 
Zitat:

Zitat von jaenicke (Beitrag 1232047)
Mit aktuelleren Versionen kannst du auch per Remote Debugger aus der Ferne den Prozess debuggen.

Ich denke bei D5 sollte das auch gehen (Jedenfalls habe ich das bei D6 schon öfters verwendet - auch wenn es nicht super-stabil und komfortabel ist)

mjustin 15. Okt 2013 08:47

AW: Quelle hoher Prozessorauslastung ermitteln
 
Enthält das Programm Schleifen, die regelmäßig ausgeführt werden? Als einfache Diagnosemöglichkeit würde sich eine Protokollierung von Ausführungszeiten relevanter Methoden anbieten. Dazu empfehle ich eine einfache Logging-Bibliothek wie log4d oder log4delphi (beide auf Sourceforge).

Auf diese Weise kann die Programmstelle, die im Laufe der Zeit immer längere CPU Auslastung erzeugt, schrittweise eingekreist werden. Bei einem Programm, das nacheinander immer drei Prozeduren A, B und C ausführt, kann man so anhand des Protokoll beobachten, welche der drei Prozeduren zunehmende Ausführungszeiten hat. Und diese dann näher betrachten.

Auch die Anzahl von Wiederholungen von Schleifen kann protokolliert werden. Programmierfehler können dazu führen, dass die Schleife öfter als notwendig ausgeführt wird und entsprechend längere Laufzeiten hat.

OlafSt 15. Okt 2013 09:13

AW: Quelle hoher Prozessorauslastung ermitteln
 
Ich denke mal, das hier große Mengen an Daten in irgendwelchen Listen gespeichert werden, ohne das diese sich leeren (oder geleert werden).

Bestes Beispiel ist das TMemo. Das einfügen neuer Strings geht anfangs ratzfatz. Mit 20k Zeilen spürt man schon deutliche Längen nach TMemo.Add, mit 30k Zeilen bewegen wir uns langsam im Sekundenbereich für das Add etcpp. Dieselben Probleme hat auch TList, TStringList, TObjectList, TGrid und und und. Dieses Phänomen habe ich schon mit Delphi 1 beobachtet und bis heute existiert dieses Problem.

Da man dieselben Laufzeiten beobachtet, wenn man eine Textdatei >5MB mit Notepad öffnet, tippe ich auf ein in der WinAPI vergrabenes Problem mit Listen aller Art.

Abhilfe: Verhindern, das diese Listen ein gewisses Maß an "Füllgrad" überschreiten oder passende Controls suchen, die nicht auf dem WinAPI-"TList" basieren.

jaenicke 15. Okt 2013 09:27

AW: Quelle hoher Prozessorauslastung ermitteln
 
Zitat:

Zitat von Bernhard Geyer (Beitrag 1232048)
Ich denke bei D5 sollte das auch gehen (Jedenfalls habe ich das bei D6 schon öfters verwendet - auch wenn es nicht super-stabil und komfortabel ist)

Theoretisch ja, aber gerade bei solchen Sachen dürfte der alte Remote Debugger an die Grenzen stoßen... probieren kann man es natürlich.

Ansonsten blieben noch Profiling Tools wie AQTime.

p80286 15. Okt 2013 11:12

AW: Quelle hoher Prozessorauslastung ermitteln
 
Zitat:

Zitat von OlafSt (Beitrag 1232055)
Ich denke mal, das hier große Mengen an Daten in irgendwelchen Listen gespeichert werden, ohne das diese sich leeren (oder geleert werden).

Bestes Beispiel ist das TMemo. Das einfügen neuer Strings geht anfangs ratzfatz. Mit 20k Zeilen spürt man schon deutliche Längen nach TMemo.Add, mit 30k Zeilen bewegen wir uns langsam im Sekundenbereich für das Add etcpp. Dieselben Probleme hat auch TList, TStringList, TObjectList, TGrid und und und. Dieses Phänomen habe ich schon mit Delphi 1 beobachtet und bis heute existiert dieses Problem.

Da man dieselben Laufzeiten beobachtet, wenn man eine Textdatei >5MB mit Notepad öffnet, tippe ich auf ein in der WinAPI vergrabenes Problem mit Listen aller Art.

Abhilfe: Verhindern, das diese Listen ein gewisses Maß an "Füllgrad" überschreiten oder passende Controls suchen, die nicht auf dem WinAPI-"TList" basieren.

Ich habe bisher noch kein Betriebssystem und keine Programmiersprache erlebt, bei denen der Zeitraum für die sequenzielle Verarbeitung von Daten, nicht proportional zur Datenmenge anwuchs. Aber vielleicht kennst Du ja Alternativen.

Gruß
K-H

Meflin 15. Okt 2013 11:41

AW: Quelle hoher Prozessorauslastung ermitteln
 
Zitat:

Zitat von p80286 (Beitrag 1232070)
Ich habe bisher noch kein Betriebssystem und keine Programmiersprache erlebt, bei denen der Zeitraum für die sequenzielle Verarbeitung von Daten, nicht proportional zur Datenmenge anwuchs. Aber vielleicht kennst Du ja Alternativen.

Ein Add, was er beschrieben hat, ist nunmal aber nicht sequentiell, sondern zum Beispiel in einer Linked List eine Operation mit konstanter Zeitkomplexität. Da dauert auch das 3,265,349. add nicht länger als das 2.

Wenn ich allerdings schon höre, dass eine Anwedung "2 Monate am Stück" laufen soll, dann wird es aber genau solche Gründe haben. An der Stelle sei mal angemerkt: Wenn es um Hochverfügbarkeit geht, geht man eigentlich genau den gegenteiligen weg: man entwirft sein System so, dass es problemlos mit Neustarts umgehen kann, und führt diese unter Umständen sogar gewollt herbei. Es sollte natürlich nicht prinzipiell unmöglich sein, eine Anwendung so zu schreiben, dass sie unendlich lange laufen kann, aber ich könnte mir durchaus vorstellen, dass der Aufwand dafür deutlich höher ist, als sich gleich ein ordentliches (und fehlertolerantes) Design zu überlegen.

BUG 15. Okt 2013 12:34

AW: Quelle hoher Prozessorauslastung ermitteln
 
Die anderen Beiträge gehen ja in die Richtung, dass die Anwendung eine graphische Anwendung ist. Die Aufgabe wäre aber eigentlich eher etwas für einen Deamon/Service.
Dazu kannst du dann eine graphische Bedienoberfläche schreiben, auf der der Anwender herumklicken kann.

Zitat:

Zitat von Meflin (Beitrag 1232074)
Es sollte natürlich nicht prinzipiell unmöglich sein, eine Anwendung so zu schreiben, dass sie unendlich lange laufen kann, aber ich könnte mir durchaus vorstellen, dass der Aufwand dafür deutlich höher ist, als sich gleich ein ordentliches (und fehlertolerantes) Design zu überlegen.

Eine Anwendung, die lange laufen soll, muss ein ordentliches und fehlertolerantes Design haben :mrgreen:

Graphische Oberflächen sind nicht ganz einfach und dank der verwendeten Bibliotheken ziemlich unübersichtlich/undurchschaubar und damit einfach ein Einfallstor für Fehler.
Also sollte man das Wichtige (Daten sammeln) von der Bedienoberfläche trennen und im Zweifelsfall einfache, stabile, gut erprobte Betriebssystemfunktionen nutzen (z.B. Dateisystem, Pipes).

Namenloser 15. Okt 2013 15:41

AW: Quelle hoher Prozessorauslastung ermitteln
 
Eure Tipps sind ja nicht schlecht, aber sie beantworten nicht die Frage des OP. Mich wundert es, dass hier noch niemand das Stichwort „Profiler“ in den Raum geworfen hat. Für Delphi gibt es da den kostenlosen SamplingProfiler, der hat mir immer gereicht.

(Man muss aber unbedingt vom Compiler eine ausführliche MAP-Datei erzeugen lassen (geht in der Projektoptionen), sonst kann man nicht viel daraus ablesen)

jaenicke 15. Okt 2013 16:26

AW: Quelle hoher Prozessorauslastung ermitteln
 
Zitat:

Zitat von NamenLozer (Beitrag 1232102)
Mich wundert es, dass hier noch niemand das Stichwort „Profiler“ in den Raum geworfen hat.

Hatte ich... ;-)
Zitat:

Zitat von jaenicke (Beitrag 1232058)
Ansonsten blieben noch Profiling Tools wie AQTime.


OlafSt 16. Okt 2013 07:13

AW: Quelle hoher Prozessorauslastung ermitteln
 
Zitat:

Nun habe ich allerdings das Problem, dass anfangs alles einwandfrei funktioniert, mit steigender Laufzeit jedoch immer längere Perioden auftreten, die den Prozessor zu 100% auslasten.
Wie man sieht, klettert die CPU-Last im laufe von Tagen immer weiter. Das schreit geradezu nach dem von mir beschriebenen Phänomen und darum empfahl ich auch, erstmal dort nachzuschauen. Das geht sicher schneller, das den Profiler nun 8 Tage mitlaufen zu lassen und dann das gleiche zu erkennen ;)

Sven M. 16. Okt 2013 15:03

AW: Quelle hoher Prozessorauslastung ermitteln
 
Stress. Stress Stress. Daher komme ich erst jetzt dazu, zu antworten. Hier ging's ja in der Zwischenzeit schon gut zur Sache. :)

Aus Zeitmangel, nehmt's mir nicht übel, in Kurzform:

1. Ja, es ist mein Programm. Das geht aus dem Taskmanager hervor.
2. Listen können es eigentlich auch nicht sein. Alle aufgenommenen Daten werden in ClientDatasets abgespeichert.
3. Die Profiling- und Log-Tools werde ich mir mal näher ansehen.

Sven M. 17. Okt 2013 09:31

AW: Quelle hoher Prozessorauslastung ermitteln
 
Okay, vielen Dank schonmal an alle bis hierhin. :thumb:
Ich bin leider noch nicht dazu gekommen, mir die Profiler und Logger anzuschauen. Trotzdem bin ich immerhin einen Schritt weiter.
Denn ich habe testweise einfach mal meine Routine zum Schreiben der Daten in die Datasets (die mit einer TLineSeries im DBChart verbunden sind) auskommentiert. Und siehe da: Keine Probleme mehr.

Delphi-Quellcode:
  if not FCDSTemperatur.Active then
  begin
    FCDSTemperatur.Open;
  end;
  FCDSTemperatur.Edit;
  FCDSTemperatur.Append;
  FCDSTemperatur.FieldByName('Zeitstempel').AsDateTime:=now;
  FCDSTemperatur.FieldByName('Wert').AsFloat:=FTemperatur;
  FCDSTemperatur.Post;
  FCDSTemperatur.SaveToFile;
Mach ich hier irgendwas Grundlegendes falsch, das die lange Rechenzeit verursacht?


edit:
Der Ordnung wegen eher eine Sache für einen neuen Thread?

OlafSt 17. Okt 2013 10:10

AW: Quelle hoher Prozessorauslastung ermitteln
 
Ich sehe da zwei potentielle Kandidaten.

1. Das
Delphi-Quellcode:
FCDSTemperatur.Open
Wird dieser Dataset immer wieder geschlossen und neu geöffnet, wird immer wieder der komplette Datenbestand aus dem Speicher geworfen und neu eingelesen. Mit steigender Datenmenge dauert dieses neu einlesen immer länger.

2.
Delphi-Quellcode:
FCDSTemperatur.SaveToFile
Natürlich dauert mit wachsendem Datenumfang das Wegschreiben des ganzen Datenbestands immer länger. Allerdings denke ich ist ClientDataSet clever genug, nur das allerneueste in die Datei zu speichern.

Ich tippe also auf ersteres und ich würde diese beiden Stellen einfach mal genauer untersuchen.

jaenicke 17. Okt 2013 10:34

AW: Quelle hoher Prozessorauslastung ermitteln
 
Es macht keinen Sinn ein TClientDataSet an dieser Stelle zu benutzen. Bei dem SaveToFile wird jedesmal die komplette Datenmenge in die XML Datei geschrieben. Dass das nicht gerade schnell ist, sollte klar sein.

Das einzig sinnvolle ist eine Embedded Datenbank, ob nun SQLite, Firebird Embedded oder MS SQL Embedded spielt dabei keine große Rolle. Da du ja (hoffentlich) nur von diesem einen Programm auf die Daten zugreifst, reicht eine Embedded Datenbank ohne echten Datenbankserver vollkommen aus.

Sven M. 21. Okt 2013 08:03

AW: Quelle hoher Prozessorauslastung ermitteln
 
Ja, das ist logisch. Bin allerdings, ebenso wie Olaf, davon ausgegangen, dass nur die neuen Datensätze weggeschrieben werden. Schade.

Gibt's zu den Embedded DBs irgendwo einsteigerfreundliche Tutorials? Bin leider noch nirgends fündig geworden. :?

Vielen Dank bis hierher! :thumb:

jaenicke 21. Okt 2013 09:04

AW: Quelle hoher Prozessorauslastung ermitteln
 
Zitat:

Zitat von Sven M. (Beitrag 1232585)
Gibt's zu den Embedded DBs irgendwo einsteigerfreundliche Tutorials? Bin leider noch nirgends fündig geworden. :?

Gibt es, ja. Erst einmal die Zugriffskomponente:
http://sqlite4delphi.sourceforge.net/
Und ein Tutorial:
http://www.delphi-treff.de/tutorials...r-fuer-delphi/

Selbst kenne ich beides nicht (ich habe immer dbExpress genutzt und nun FireDAC, aber das hast du nicht), habe aber viel Gutes darüber gelesen.

Sven M. 21. Okt 2013 13:58

AW: Quelle hoher Prozessorauslastung ermitteln
 
Moah, ich brauch' Urlaub, kann nicht mal mehr anständig googeln...

Recht herzlichen Dank!8-)
Ich fuchs' mich da mal rein.


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:07 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz