Connaitre l'occupation des CPU par l'pplication [Résolu]

cs_Gerard 121 Messages postés jeudi 10 janvier 2002Date d'inscription 17 mars 2017 Dernière intervention - 12 mai 2014 à 10:51 - Dernière réponse : korgis 415 Messages postés samedi 17 mai 2003Date d'inscription 11 mai 2018 Dernière intervention
- 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.


--
Afficher la suite 

Votre réponse

5 réponses

korgis 415 Messages postés samedi 17 mai 2003Date d'inscription 11 mai 2018 Dernière intervention - 14 mai 2014 à 23:36
0
Merci
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
Commenter la réponse de korgis
korgis 415 Messages postés samedi 17 mai 2003Date d'inscription 11 mai 2018 Dernière intervention - Modifié par korgis le 17/05/2014 à 13:23
0
Merci
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
Commenter la réponse de korgis
korgis 415 Messages postés samedi 17 mai 2003Date d'inscription 11 mai 2018 Dernière intervention - 18 mai 2014 à 14:28
0
Merci
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...
Commenter la réponse de korgis
cs_Gerard 121 Messages postés jeudi 10 janvier 2002Date d'inscription 17 mars 2017 Dernière intervention - 18 mai 2014 à 15:58
0
Merci
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!


--
korgis 415 Messages postés samedi 17 mai 2003Date d'inscription 11 mai 2018 Dernière intervention - 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...
Commenter la réponse de cs_Gerard

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.