Nous connaissons tous la commande top (ou mieux htop) qui donne, à un instant T, l'utilisation CPU par processus. Mais comment connaître l'utilisation CPU consommée par tous les processus d'un utilisateur. J'ai eu beau chercher, je n'ai rien trouvé.

J'ai donc pris le temps d'écrire (en ruby) un script qui permet d'obtenir ces statistiques. Pour fonctionner, il faut un ruby 1.8.7 (ou peut-être moins), un kernel récent pour avoir les statistiques IO (>= RHEL5.5).

Le script affiche en sortie trois informations:

  • le nom de l'utilisateur
  • le pourcentage de CPU consommé entre 2 exécutions
  • le temps d'attente en IO

Les informations sont calculées à partir des pseudos-fichiers /proc. Chaque processus possède ces pseudos-fichiers qui sont mis à jour par le kernel et le fichier intéressant est stat. Dans ce fichier, on trouve aux champs 14 et 15:

  • CPU time spent in user code, measured in jiffies soit le temps passé par le processus (code utilisateur) mesuré en jiffies
  • CPU time spent in kernel code, measured in jiffies soit le temps passé par le processus (code kernel) mesuré en jiffies

Pour les autres champs, c'est par ici

Donc, dès qu'un processus utilise des cycles CPU, le kernel comptabilise le temps accordé dans ces deux champs, en différenciant le temps consommé par le code du processus (user mode) et le code système (system mode).

Mais que vaut un jiffy?

C'est une constante que l'on peut retrouver dans les fichiers include du kernel sous le nom HZ. Pour les CPU i386 et x86_64 (Intel ou AMD), cette valeur est de 100. (cf /usr/include/asm-generic/param.h). Donc, 1 jiffy vaut 0.1 seconde.

Qu'avons nous allors?

Il est possible de connaître tous les processus en cours de fonctionnement. Via le pseudo-fichier stat, il est possible d'avoir le nombre total de jiffies en usermode et systemmode depuis le lancement du processus. Il ne reste plus qu'a faire la différence de ces deux valeurs entre deux lectures. Pour cela, il faut donc mémoriser ces valeurs dans un fichier d'historique, avec l'heure de lecture et à la prochaine lecture, d'en faire la différence. On a alors le temps consommé par un processus en jiffies par seconde.

Il suffit enfin à grouper tous les processus par utilisateur et d'additionner le total CPU.

Exemple d'utilisation:

$ ./utop.rb
User            CPU%  IO%
root               1    1
davidb            22    0
statd              0    0
syslog             0    0
messagebus         0    0
avahi              0    0
colord             0    0
cntlm              0    0
nobody             0    0
whoopsie           0    0
rtkit              0    0
ntp                0    0
www-data           0    0

Mise en garde

Si un processus est lancé juste après la dernière lecture et se termine juste avant la prochaine lecture, aucune statistique ne sera comptabilisée, car le pseudo-fichier stat aura disparu. Cela est d'autant plus vrai que la fréquence d'actualisation est petite (long intervalle entre deux exécutions).https://github.com/david-barbion/system/tree/master/u-top

Téléchargement

Les sources sont disponibles ici: https://github.com/david-barbion/system/tree/master/u-top