Get Cpu_Usage (CPU-Auslastung)

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Frank Ranis
Beiträge: 201
Registriert: Do 24. Jan 2013, 21:22

Get Cpu_Usage (CPU-Auslastung)

Beitrag von Frank Ranis »

Hi,

ich suche eine Funktion , um die aktuelle CPU-Auslastung zu lesen , muß in Windows und Linux funzen.

Vor Jahren hatte ich mal folgenden Code gefunden (weis leider nicht mehr woher).
Dieser funktoniert aber nur unter Windows .

Code: Alles auswählen

unit CpuUsage;
 
{$mode delphi}
 
interface
 
uses
  Classes,
  SysUtils,
  JwaWinBase;
 
var
  FLastIdleTime: Int64;
  FLastKernelTime: Int64;
  FLastUserTime: Int64;
 
function get_cpu_last:double;
 
implementation
 
(******************)
(* CPU-Last holen *)
(******************)
function get_cpu_last:double;
{$PUSH}
{$CODEALIGN LOCALMIN=8}
var
  IdleTimeRec: TFileTime;
  KernelTimeRec: TFileTime;
  UserTimeRec: TFileTime;
  IdleTime: Int64 absolute IdleTimeRec;
  KernelTime: Int64 absolute KernelTimeRec;
  UserTime: Int64 absolute UserTimeRec;
  IdleDiff: Int64;
  KernelDiff: Int64;
  UserDiff: Int64;
  SysTime: Int64;
{$POP}
var last:double;
begin
 result:=0;
 if GetSystemTimes(@IdleTimeRec, @KernelTimeRec, @UserTimeRec)
 then
  begin
    IdleDiff := IdleTime - FLastIdleTime;
    KernelDiff := KernelTime - FLastKernelTime;
    UserDiff := UserTime - FLastUserTime;
    FLastIdleTime := IdleTime;
    FLastKernelTime := KernelTime;
    FLastUserTime := UserTime;
    SysTime := KernelDiff + UserDiff;
    last:=(SysTime - IdleDiff)/SysTime * 100;
    result:=last;
  end;
end;
 
end.
 

Gruß

Frank
www.flz-vortex.de

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

Re: Get Cpu_Usage (CPU-Auslastung)

Beitrag von theo »

Nicht ganz einfach.
Vllt. hilft das weiter. https://stackoverflow.com/questions/301 ... ux-using-c
Was wäre denn der Sinn der Sache?

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Get Cpu_Usage (CPU-Auslastung)

Beitrag von Warf »

Für windows sollte das sein was du suchst: Link

Für ein beispiel in C schau mal hier: Link

Frank Ranis
Beiträge: 201
Registriert: Do 24. Jan 2013, 21:22

Re: Get Cpu_Usage (CPU-Auslastung)

Beitrag von Frank Ranis »

Hallo ,

danke für eure Antworten .

Warf hat geschrieben:Für windows sollte das sein was du suchst: Link

Für ein beispiel in C schau mal hier: Link
theo hat geschrieben:Nicht ganz einfach.
Vllt. hilft das weiter. https://stackoverflow.com/questions/301 ... ux-using-c
Was wäre denn der Sinn der Sache?


Beim 'C' bekomme ich aber das Würgen , mit C -> Pascal kenne ich mich überhaupt nicht aus .
Hatte halt die Hoffnung , das dafür schon mal jemand was in Pascal geschrieben hat.

Gruß

Frank
www.flz-vortex.de

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Get Cpu_Usage (CPU-Auslastung)

Beitrag von af0815 »

Soweit ich das verstehe kann man diese Informationen übert das lesen von /proc/stat und weiterer Systemdateine unter Linux abfragen. Die Beispiele in C sind aber auch für einen Pascalprogrammierer lesbar, da ist keine C/C++ gefrickel drinnen.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Frank Ranis
Beiträge: 201
Registriert: Do 24. Jan 2013, 21:22

Re: Get Cpu_Usage (CPU-Auslastung)

Beitrag von Frank Ranis »

Hi,

af0815 hat geschrieben:Soweit ich das verstehe kann man diese Informationen übert das lesen von /proc/stat und weiterer Systemdateine unter Linux abfragen. Die Beispiele in C sind aber auch für einen Pascalprogrammierer lesbar, da ist keine C/C++ gefrickel drinnen.


ich bin totaler Neueinsteiger in Sachen Linux , kann mit /proc/stat noch nichts anfangen.
Gibt es Code-Beispiele (Pascal) wie man da rann kommt ?

Gruß

Frank
www.flz-vortex.de

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Get Cpu_Usage (CPU-Auslastung)

Beitrag von m.fuchs »

Da hätte ich noch was rumliegen:

Code: Alles auswählen

program ReadProc;
{$mode objfpc}{$H+}
 
uses
  Classes, SysUtils, StrUtils, Math;
 
type
  TCpuData = record
    User, Nice, System, Idle, All: Integer;
  end;
 
function GetFileContent(Filename: String): TStringList;
begin
  Result := TStringList.Create;
  if FileExists(Filename) then
    Result.LoadFromFile(Filename);
end;
 
function GetCpuData: TCpuData;
var
  sl: TStringList;
begin
  {$IfDef WINDOWS}
  {$ELSE}
    try
      sl := GetFileContent('/proc/stat');
      Result.User := StrToInt(ExtractWord(2, sl[0], StdWordDelims));
      Result.Nice := StrToInt(ExtractWord(3, sl[0], StdWordDelims));
      Result.System := StrToInt(ExtractWord(4, sl[0], StdWordDelims));
      Result.Idle := StrToInt(ExtractWord(5, sl[0], StdWordDelims));
      Result.All := Result.User + Result.Nice + Result.System + Result.Idle;
    finally
      FreeAndNil(sl);
    end;
  {$EndIf}
end;
 
function GetUptimeResult: String;
var
  sl: TStringList;
  Unixtimes, Seconds, Minutes, Hours, Days: Integer;
begin
  {$IfDef WINDOWS}
     Result := '99 Tage, 20 Stunden, 15 Minuten, 6 Sekunden';
  {$Else}
    try
      sl := GetFileContent('/proc/uptime');
      Unixtimes := StrToInt(Copy2Symb(sl[0], '.'));
      Days := Unixtimes div 86400;
      Unixtimes := Unixtimes mod 86400;
      Hours := Unixtimes div 3600;
      Unixtimes := Unixtimes mod 3600;
      Minutes := Unixtimes div 60;
      Seconds := Unixtimes mod 60;
      Result := Format('%d Tage, %d Stunden, %d Minuten, %d Sekunden', [Days, Hours, Minutes, Seconds])
    finally
      FreeAndNil(sl);
    end;
  {$EndIf}
end;
 
var
  CpuData: TCpuData;
 
begin
  CpuData := GetCpuData;
  WriteLn('User: ', CpuData.User);
  WriteLn('Nice: ', CpuData.Nice);
  WriteLn('System: ', CpuData.System);
  WriteLn('Idle: ', CpuData.Idle);
  WriteLn('All: ', CpuData.All);
  WriteLn();
  WriteLn(GetUptimeResult);
end.
 
 
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Frank Ranis
Beiträge: 201
Registriert: Do 24. Jan 2013, 21:22

Re: Get Cpu_Usage (CPU-Auslastung)

Beitrag von Frank Ranis »

Hi ,

super , vielen Dank , jetzt habe ich was zum spielen .
Und dann schau ich mir noch mal die oben angegeben LINKS näher an .

m.fuchs hat geschrieben:Da hätte ich noch was rumliegen:

Code: Alles auswählen

program ReadProc;
{$mode objfpc}{$H+}
 
uses
  Classes, SysUtils, StrUtils, Math;
 
type
  TCpuData = record
    User, Nice, System, Idle, All: Integer;
  end;
 
function GetFileContent(Filename: String): TStringList;
begin
  Result := TStringList.Create;
  if FileExists(Filename) then
    Result.LoadFromFile(Filename);
end;
 
function GetCpuData: TCpuData;
var
  sl: TStringList;
begin
  {$IfDef WINDOWS}
  {$ELSE}
    try
      sl := GetFileContent('/proc/stat');
      Result.User := StrToInt(ExtractWord(2, sl[0], StdWordDelims));
      Result.Nice := StrToInt(ExtractWord(3, sl[0], StdWordDelims));
      Result.System := StrToInt(ExtractWord(4, sl[0], StdWordDelims));
      Result.Idle := StrToInt(ExtractWord(5, sl[0], StdWordDelims));
      Result.All := Result.User + Result.Nice + Result.System + Result.Idle;
    finally
      FreeAndNil(sl);
    end;
  {$EndIf}
end;
 
function GetUptimeResult: String;
var
  sl: TStringList;
  Unixtimes, Seconds, Minutes, Hours, Days: Integer;
begin
  {$IfDef WINDOWS}
     Result := '99 Tage, 20 Stunden, 15 Minuten, 6 Sekunden';
  {$Else}
    try
      sl := GetFileContent('/proc/uptime');
      Unixtimes := StrToInt(Copy2Symb(sl[0], '.'));
      Days := Unixtimes div 86400;
      Unixtimes := Unixtimes mod 86400;
      Hours := Unixtimes div 3600;
      Unixtimes := Unixtimes mod 3600;
      Minutes := Unixtimes div 60;
      Seconds := Unixtimes mod 60;
      Result := Format('%d Tage, %d Stunden, %d Minuten, %d Sekunden', [Days, Hours, Minutes, Seconds])
    finally
      FreeAndNil(sl);
    end;
  {$EndIf}
end;
 
var
  CpuData: TCpuData;
 
begin
  CpuData := GetCpuData;
  WriteLn('User: ', CpuData.User);
  WriteLn('Nice: ', CpuData.Nice);
  WriteLn('System: ', CpuData.System);
  WriteLn('Idle: ', CpuData.Idle);
  WriteLn('All: ', CpuData.All);
  WriteLn();
  WriteLn(GetUptimeResult);
end.
 
 


Gruß

Frank
www.flz-vortex.de

Frank Ranis
Beiträge: 201
Registriert: Do 24. Jan 2013, 21:22

Re: Get Cpu_Usage (CPU-Auslastung)

Beitrag von Frank Ranis »

Hi ,

aus den ganzen Infos und dem Code-Beispiel von (m.fuchs) habe ich jetzt mal ein Demo gebaut.
Ist ja eingentlich ganz einfach , wenn man erst mal eine Schubs bekommt .

Habe für das einlesen von '/proc/stat' mal ein Memo genommen , da sieht man alles schön im Klartext.
Später nimmt man dann halt eine Stringlist im verborgenen.

In Button1.click wird das Memo ausgewertet .
Und ein Timer triggert den Button in gewissen Abständen.

Code: Alles auswählen

unit Unit1;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  ExtCtrls ;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Memo2: TMemo;
    Timer1: TTimer;  // Interval auf 250ms eingestellt
    procedure Button1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
 
  public
 
  end;
 
var
  Form1: TForm1;
  str1,str2:string;
 
implementation
 
{$R *.lfm}
 
{ TForm1 }
 
procedure TForm1.Button1Click(Sender: TObject);
var prozesor_count,i,p:integer;
    z,w1,w2:string;
    array1,array2:tstringarray;
    total_1,work_1,total_2,work_2:integer;
    work_over_period,total_over_period:integer;
    cpu_last_proz:double;
begin
 // Timer während der Auswertung abschalten
 // damit einem nich ein neuer Timeraufruf dazwischenfunkt
 timer1.Enabled:=false;
 
 // Hier wird jetzt mal ein Memo genommen , um alles visuell zu betrachten
 // später dann eine Stringlist benutzen
 memo2.Lines.BeginUpdate;
 memo2.Lines.LoadFromFile('/proc/stat');
 memo2.Lines.EndUpdate;
 
 // Anzahl der verfügbaren Prozessorkerne ermitteln , weil man die Information
 // auch im '/proc/stat' geliefert bekommt .
 // Könnte man in eine separate Funktion auslagern , da ja die eigentliche
 // Aufgabe die Berechnung der Prozessor-Last ist
 prozesor_count:=0;
 for i:=0 to memo2.Lines.Count-1 do
  begin
   z:=uppercase(memo2.Lines[i]);
   if pos('CPU',z)>0 then inc(prozesor_count);
  end;
 // Einen weniger , weil in der ersten Zeile von '/proc/stat' die
 // Gesamt-Prozessor-Infos stehen
 dec(prozesor_count);
 
 // Gesamtprozessorlast berechnen
 if str1=''                  // beim allerersten Timerdurchlauf
  then str1:=memo2.Lines[0]
  else                       // bei allen weiteren Timerdurchläufen
   begin
    memo1.Clear;
    memo1.Lines.Add('Anzahl Prozessorkerne = '+inttostr(prozesor_count));
 
    str2:=memo2.Lines[0];
 
    // Für interne Stringzerlegung kopieren
    w1:=str1;
    w2:=str2;
 
    // Teilstring , Cpu-Text löschen
    // und Vorlauf-Leerzeichen beseitigen
    delete(w1,1,pos(' ',w1));
    w1:=trimleft(w1);
    delete(w2,1,pos(' ',w2));
    w2:=trimleft(w2);
 
    // str1 und str2 in arrays zerlegen
    array1:=w1.split(' ');
    array2:=w2.split(' ');
 
    // Summen berechnen
    // Vorgehensweise ist unter
    // https://stackoverflow.com/questions/301 ... ux-using-c
    // beschrieben
 
    // total_1 = (sum of all values) array1
    total_1:=0;
    for i:=0 to 9 do
     total_1:=total_1+strtoint(array1[i]);
    // work_1 = (sum of user,nice,system = the first 3 values) array1
    work_1:=0;
    for i:=0 to 2 do
     work_1:=work_1+strtoint(array1[i]);
 
    // total_2 = (sum of all values) array2
    total_2:=0;
    for i:=0 to 9 do
     total_2:=total_2+strtoint(array2[i]);
    // work_1 = (sum of user,nice,system = the first 3 values) array2
    work_2:=0;
    for i:=0 to 2 do
     work_2:=work_2+strtoint(array2[i]);
 
    // Verrechnen
    // So the %cpu usage over this period is:
    work_over_period:= work_2 - work_1;
    total_over_period:= total_2 - total_1;
    // %cpu = work_over_period / total_over_period * 100
    cpu_last_proz:=work_over_period / total_over_period * 100;
 
    memo1.Lines.Add('Gesamt-Prozessorlast = '+FormatFloat('000.0',cpu_last_proz)+'[%]');
 
    str1:=str2;
   end;
 
 // Timer wieder scharf schalten
 timer1.Enabled:=true;
end;
 
procedure TForm1.Timer1Timer(Sender: TObject);
begin
 button1.click;
end;
 
initialization
 
 str1:='';
 str2:='';
 
end.
 


Als nächstes bau ich mir noch ne Unit in der dann OS-abhängig , die Linux- oder Windows-Funktion kompiliert wird.

Alles super , ich danke euch .

Linux-Demo im Anhang.

Gruß

Frank
Dateianhänge
lazarus_linux_get_cpu_usage.zip
Linux-Demo
(1.87 MiB) 125-mal heruntergeladen
www.flz-vortex.de

laz_frank
Beiträge: 14
Registriert: Mi 3. Okt 2012, 20:31
OS, Lazarus, FPC: Winux64 (Laz 2.1.0 FPC 3.3.1)
CPU-Target: x86-64

Re: Get Cpu_Usage (CPU-Auslastung)

Beitrag von laz_frank »

Hallo Frank,

vielen Dank für das Beispiel, die sequentielle Programmgestaltung, die Aufteilung in kleinste Funktionsschritte und die ausführliche Erläuterung in den Kommentaren! Genau so sollten Demo-Programme meiner Meinung nach aussehen. 8)
Gruß, Frank

Antworten