Connaitre l'occupation des CPU par l'pplication

Résolu
cs_Gerard Messages postés 121 Date d'inscription jeudi 10 janvier 2002 Statut Membre Dernière intervention 7 août 2018 - 12 mai 2014 à 10:51
korgis Messages postés 420 Date d'inscription samedi 17 mai 2003 Statut Membre Dernière intervention 6 mai 2019 - 21 mai 2014 à 21:14
Bonjour,
Il arrive que mon serveur reste avec une activité résiduelle importante (>20%) des CPU alors qu'il est sensé ne rien faire.
Est-il possible que l'application connaisse la charge CPU qu'elle crée?
Merci.


--

4 réponses

korgis Messages postés 420 Date d'inscription samedi 17 mai 2003 Statut Membre Dernière intervention 6 mai 2019 17
14 mai 2014 à 23:36
Salut,

Là, c'est un poil plus compliqué que de récupérer l'occupation mémoire.

En gros, il te faut récupérer les valeurs "IdleTime", "KernelTime" et "UserTime" au moyen d'une fonction callback utilisant "GetSystemTimes" dans l'api windows, après avoir récupéré le handle (de cette fonction) au moyen de "GetProcAddress".

Il faut ensuite s'occuper des valeurs récupérées, et là je ne sais pas trop comment m'en servir...

Dommage pour toi (et pour nous) que les "pointures" aient déserté le site.
On fait juste un peu d'entretien pour pas laisser Delphifr rouiller.
On met un peu d'huile.
On veille à ce que la petite lumière reste allumée.
En attendant que ça redevienne comme avant. (*)
Et que Nix revienne.
(je déc... heu rigole ^^)

(*) Même si la tarte au concombre c'est complètement dég... sagréable
0
korgis Messages postés 420 Date d'inscription samedi 17 mai 2003 Statut Membre Dernière intervention 6 mai 2019 17
Modifié par korgis le 17/05/2014 à 13:23
En fait, il faut :

- récupérer les valeurs IdleTime, KernelTime, UserTime comme décrit précédemment,
- convertir ces valeurs en Int64 (QuadWord selon la terminologie Microsoft),
- faire la même chose un laps de temps plus tard (1000 millisec par exemple).

Puis appliquer ce calcul aux valeurs obtenues, qu'on appellera par exemple respectivement ElapsedIdleTime, ElapsedKernelTime, ElapsedUserTime :

CpuUsedByAppli := 
    Trunc(
         (ElapsedKernelTime + ElapsedUserTime - ElapsedIdleTime)
         /
         (ElapsedKernelTime + ElapsedUserTime)
         *
         100
         );

Voila pour le principe, j'ai testé, ça fonctionne bien.

Si j'ai le temps (et si ça intéresse quelqu'un) je balance un bout de code et son utilisation, mais il faut que je nettoie
(ça a été assez laborieux pour arriver au résultat... :-p)

Bon week-end à tous et à toutes.

korgis
0
korgis Messages postés 420 Date d'inscription samedi 17 mai 2003 Statut Membre Dernière intervention 6 mai 2019 17
18 mai 2014 à 14:28
Ouvrir un nouveau projet.

Poser en vrac :
- 1 TButton,
- 1 TTimer,
- 1 TLabel,
Ajouter la procedure "procedure DoAnything" dans private (ou dans public, I don't care (et j'm'en fous)).

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    Button1: TButton;
    Label1: TLabel;      // 1 TLabel
    procedure Timer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button1Click(Sender: TObject);
  private
    { Déclarations privées }
    procedure DoAnything;   // 1 procedure
  public
    { Déclarations publiques }
  end;

Associer les évènements :
- OnCreate du TForm,
- OnClose du TForm,
- OnTimer du TTimer,
- OnClick du TButton
au code ci-après,
sans oublier de copier coller le reste du code !

implementation

{$R *.DFM}

// conversion d'une valeur TFileTime en Int64
function FileTimeToQuadWord(FileTime: TFileTime): Int64;
begin
  Result := (FileTime.dwHighDateTime shl 32) +  FileTime.dwLowDateTime;
end;

// utilisé par GetCpuUsedByAppli, à laisser au-dessus
var
  IdleTimeOld: TFileTime;
  KernelTimeOld: TFileTime;
  UserTimeOld: TFileTime;

function GetCpuUsedByAppli: Integer;
type
  TGetSystemTimes = function(const IdleTime, KernelTime, UserTime: PFileTime): Boolean; stdcall;
var
  ModuleHandle: THandle;
  GetSystemTimes: TGetSystemTimes;
  IdleTimeNow: TFileTime;
  KernelTimeNow: TFileTime;
  UserTimeNow: TFileTime;
  ElapsedIdleTime: Cardinal;
  ElapsedKernelTime: Cardinal;
  ElapsedUserTime: Cardinal;
begin
  Result := -1;
  ModuleHandle := GetModuleHandle(PChar('kernel32.dll'));
  @GetSystemTimes := GetProcAddress(ModuleHandle, PChar('GetSystemTimes'));
  if Assigned(GetSystemTimes) then
    if GetSystemTimes(@IdleTimeNow, @KernelTimeNow, @UserTimeNow) then
    begin
      ElapsedIdleTime := FileTimeToQuadWord(IdleTimeNow) - FileTimeToQuadWord(IdleTimeOld);
      ElapsedKernelTime := FileTimeToQuadWord(KernelTimeNow) - FileTimeToQuadWord(KernelTimeOld);
      ElapsedUserTime := FileTimeToQuadWord(UserTimeNow) - FileTimeToQuadWord(UserTimeOld);
      if (ElapsedIdleTime < 0) or (ElapsedKernelTime < 0) or (ElapsedUserTime < 0) then Exit;
      Result := Trunc(
                      (ElapsedKernelTime + ElapsedUserTime - ElapsedIdleTime)
                      /
                      (ElapsedKernelTime + ElapsedUserTime)
                      *
                      100
                      );
      if Result > 100 then Result := -1;
      IdleTimeOld := IdleTimeNow;
      KernelTimeOld := KernelTimeNow;
      UserTimeOld := UserTimeNow;
    end;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  CpuUsedByAppli: Integer;
begin
  CpuUsedByAppli := GetCpuUsedByAppli;
  Label1.Caption := Format('Taux d''utilisation = %d%%', [CpuUsedByAppli]);
end;

var
  Stop: Boolean;

procedure TForm1.FormCreate(Sender: TObject);
begin
  // Quick interface settings for idle... ;-)
  Caption := 'Taux cpu utilisé par l''appli';
  Height := 179;
  Width := 285;
  Position := poScreenCenter;
  with Button1 do
  begin
    Left := 108;
    Top := 72;
    Caption := 'Off';
  end;
  with Label1 do
  begin
    Left := 88;
    Top := 28;
    Caption := 'Taux d''utilisation =';
  end;
  
  Stop := True;
  Timer1.Interval := 500;   // <- à régler selon la précision souhaitée
  Timer1.Enabled := True;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Stop := True;
end;

{
_______________________________________________________________________________

     TEST : LANCEMENT D'UNE TACHE POUR AUGMENTER L'UTILISATION DU CPU
_______________________________________________________________________________
}
  
procedure TForm1.DoAnything;  // n'importe quoi...
var
  i: Integer;
  R: Int64;
begin
  Stop := not Stop;
  Button1.Caption := 'On';
  for i := 1 to 5000000 do
  begin
    R := (i * 15) div 13;
    R := R + R * 7;
    Caption := IntToStr(R);
    Application.ProcessMessages;
    if Stop then
      Break;
  end;
  Button1.Caption := 'Off';
  Stop := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  DoAnything;
end;


Agiter, (com)piler, à servir frais...
0
cs_Gerard Messages postés 121 Date d'inscription jeudi 10 janvier 2002 Statut Membre Dernière intervention 7 août 2018
18 mai 2014 à 15:58
Merci cela marche!
J'avais essayé avec une function external mais j'avais toujours des 0...
Je n'avais pas bien défini les pFileTime me semble-t-il....

je l'intègre au projet et je fermerai la question si ceal fait ce que je cherche!
merci en tout cas!


--
0
korgis Messages postés 420 Date d'inscription samedi 17 mai 2003 Statut Membre Dernière intervention 6 mai 2019 17
21 mai 2014 à 21:14
Pas de quoi.
Question intéressante, qui m'a personnellement fait progresser dans certains aspects de l'utilisation de l'api windows...
0
Rejoignez-nous