web-dev-qa-db-fra.com

Déterminer correctement l'utilisation de la mémoire sous Linux

Je suis un peu confus sur certains des résultats que je vois de ps et free.

Sur mon serveur, c'est le résultat de free -m

[root@server ~]# free -m
             total       used       free     shared    buffers     cached
Mem:          2048       2033         14          0         73       1398
-/+ buffers/cache:        561       1486
Swap:         2047         11       2036

Ma compréhension de la façon dont Linux gère la mémoire, c'est qu'il stockera l'utilisation du disque dans la RAM, afin que chaque accès ultérieur soit plus rapide. Je crois que cela est indiqué par les colonnes "en cache". De plus, divers tampons sont stockés dans la RAM, indiqués dans la colonne "tampons".

Donc, si je comprends bien, l'utilisation "réelle" est censée être la valeur "utilisée" de "-/+ buffers/cache", ou 561 dans ce cas.

Donc, en supposant que tout cela est correct, la partie qui me jette est le résultat de ps aux.

Ma compréhension des résultats ps est que la 6ème colonne (RSS) représente la taille en kilo-octets que le processus utilise pour la mémoire.

Ainsi, lorsque j'exécute cette commande:

[root@server ~]# ps aux | awk '{sum+=$6} END {print sum / 1024}'
1475.52

Le résultat ne devrait-il pas être la colonne "utilisé" de "-/+ buffers/cache" de free -m?

Alors, comment puis-je déterminer correctement l'utilisation de la mémoire d'un processus sous Linux? Apparemment, ma logique est défectueuse.

66
GoldenNewby

Cette exacte même question a été posée le serverfault l'autre jour :-)

Le système de mémoire virtuelle Linux n'est pas aussi simple. Vous ne pouvez pas simplement ajouter tous les champs RSS et obtenir la valeur signalée used par free. Il y a plusieurs raisons à cela, mais j'en toucherai quelques-unes.

  • Lorsqu'un processus bifurque, le parent et l'enfant s'affichent avec le même RSS. Cependant Linux utilise copy-on-write pour que les deux processus utilisent réellement la même mémoire. Ce n'est que lorsque l'un des processus modifie la mémoire qu'elle sera effectivement dupliquée. Ainsi, le nombre free sera plus petit que la somme RSS top.

  • La valeur RSS n'inclut pas la mémoire partagée. La mémoire partagée n'appartenant à aucun processus, top ne l'inclut pas dans RSS. Ainsi, le nombre free sera plus grand que la somme RSS top.

57
Patrick

Si vous recherchez des numéros de mémoire qui s'additionnent, jetez un œil à smem :

smem est un outil qui peut fournir de nombreux rapports sur l'utilisation de la mémoire sur les systèmes Linux. Contrairement aux outils existants, smem peut signaler une taille de jeu proportionnelle (PSS), qui est une représentation plus significative de la quantité de mémoire utilisée par les bibliothèques et les applications dans un système de mémoire virtuelle.

Étant donné que de grandes parties de la mémoire physique sont généralement partagées entre plusieurs applications, la mesure standard de l'utilisation de la mémoire connue sous le nom de taille de l'ensemble résident (RSS) surestimera considérablement l'utilisation de la mémoire. PSS mesure à la place la "part équitable" de chaque application de chaque zone partagée pour donner une mesure réaliste.

Par exemple ici:

# smem -t
  PID User     Command                         Swap      USS      PSS      RSS
...
10593 root     /usr/lib/chromium-browser/c        0    22868    26439    49364 
11500 root     /usr/lib/chromium-browser/c        0    22612    26486    49732 
10474 browser  /usr/lib/chromium-browser/c        0    39232    43806    61560 
 7777 user     /usr/lib/Thunderbird/thunde        0    89652    91118   102756 
-------------------------------------------------------------------------------
  118 4                                       40364   594228   653873  1153092 

Donc PSS est la colonne intéressante ici car elle prend en compte la mémoire partagée.
Contrairement à RSS, il est utile de l'additionner. Nous obtenons 654 Mo au total pour les processus de l'espace utilisateur ici.

La sortie à l'échelle du système raconte le reste:

# smem -tw
Area                           Used      Cache   Noncache 
firmware/hardware                 0          0          0 
kernel image                      0          0          0 
kernel dynamic memory        345784     297092      48692 
userspace memory             654056     181076     472980 
free memory                   15828      15828          0 
----------------------------------------------------------
                            1015668     493996     521672 

Donc 1 Go RAM totale = 654Mb processus de l'espace utilisateur + 346Mb mem du noyau + 16 Mo gratuit
(donner ou prendre quelques Mb)

Globalement, environ la moitié de la mémoire est utilisée pour le cache (494 Mo).

Question bonus : qu'est-ce que le cache userland vs le cache noyau ici?


btw pour quelque chose d'essayage visuel:

# smem  --pie=name

enter image description here

31
lemonsqueeze

Un très bon outil est pmap qui répertorie l'utilisation actuelle de la mémoire pour un certain processus:

pmap -d PID

Pour plus d'informations à ce sujet, consultez la page de manuel man pmap et jetez également un œil à 20 outils de surveillance du système Linux que chaque administrateur système devrait connaître , qui répertorie les excellents outils que j'utilise toujours pour obtenir des informations sur ma boîte Linux.

14
ByteNudger

Exécutez top, appuyez sur h pour obtenir de l'aide puis f pour ajouter des champs. vous pouvez ajouter les champs suivants:

  • RSS quantité de mémoire physique utilisée par l'application
  • CODE quantité totale de mémoire utilisée par le code exécutable du processus
  • DATA - quantité totale de mémoire (ko) dédiée aux données et à la pile d'un processus

Entre ces 3, vous devriez avoir des résultats assez précis. Vous pouvez également utiliser des remplacements plus détaillés pour le haut Je recommande htop ou atop.

Edit: Presque oublié si vous voulez des informations vraiment détaillées. Trouvez le PID et cat le fichier suivant.

PID=123

cat /proc/123/status

Edit 2: Si vous pouvez le trouver ou l'avoir le livre:

Optimisation des performances Linux: guide pratique des outils de performances Linux

-a une section Chapitre 5: Outils de performance: Mémoire spécifique au processus -il contient bien plus d'informations que vous ne le souhaiteriez.

10
2bc

ps vous donne la quantité de mémoire utilisée par chaque processus. Une partie de cette mémoire est constituée de fichiers mmappés, qui comptent dans le cache. Une partie de cette mémoire (en particulier le code) est partagée avec d'autres processus, donc si vous additionnez les valeurs RSS, elle est comptée plusieurs fois.

Il n'y a pas de bonne réponse à "combien de mémoire ce processus utilise-t-il?", Car il ne dépend pas uniquement du processus, il dépend aussi de l'environnement. Il existe de nombreuses valeurs différentes que vous pourriez appeler "l'utilisation de la mémoire" du processus, et elles ne correspondent pas ou ne s'additionnent pas car elles comptent des choses différentes.

Comme d'autres l'ont correctement souligné, il est difficile d'avoir une idée de la mémoire réelle utilisée par un processus, des régions partagées, des fichiers mmap et ainsi de suite.

Si vous êtes un expérimentateur, vous pouvez exécuter valgrind et massif . Cela peut devenir un peu lourd pour l'utilisateur occasionnel, mais vous aurez une idée du comportement de la mémoire d'une application au fil du temps. Si une application malloc () est exactement ce dont elle a besoin, cela vous donnera une bonne représentation de l'utilisation réelle de la mémoire dynamique d'un processus. Mais cette expérience peut être "empoisonnée".

Pour compliquer les choses, Linux vous permet de surcharger votre mémoire. Lorsque vous mémoire malloc (), vous déclarez votre intention de consommer de la mémoire. Mais l'allocation ne se produit vraiment que lorsque vous écrivez un octet dans une nouvelle page de votre "RAM" allouée. Vous pouvez le prouver en écrivant et en exécutant un petit programme C comme ceci:

// test.c
#include <malloc.h>
#include <stdio.h>
#include <unistd.h>
int main() {
    void *p;
    sleep(5)
    p = malloc(16ULL*1024*1024*1024);
    printf("p = %p\n", p);
    sleep(30);
    return 0;
}

# Shell:
cc test.c -o test && ./test &
top -p $!

Exécutez ceci sur une machine avec moins de 16 Go de RAM et, le tour est joué !, vous venez de marquer 16 Go de mémoire! (Non, pas vraiment).

Remarquez dans top vous voyez "VIRT" comme 16.004G mais% MEM est 0.0

Exécutez à nouveau avec valgrind:

# Shell:
valgrind --tool=massif ./test &
sleep 36
ms_print massif.out.$! | head -n 30

Et massif dit "somme de toutes les allocations () = 16 Go". Ce n'est donc pas très intéressant.

MAIS, si vous l'exécutez sur un processus sain :

# Shell:
rm test test.o
valgrind --tool=massif cc test.c -o test &
sleep 3
ms_print massif.out.$! | head -n 30

--------------------------------------------------------------------------------
Command:            cc test.c -o test
Massif arguments:   (none)
ms_print arguments: massif.out.23988
--------------------------------------------------------------------------------


    KB
77.33^                                                                       :
     |                                                                      #:
     |                                                                :@::@:#:
     |                                                           :::::@@::@:#:
     |                                                         @:: :::@@::@:#:
     |                                                     ::::@:: :::@@::@:#:
     |                                             ::@:::@:::::@:: :::@@::@:#:
     |                                            @::@:::@:::::@:: :::@@::@:#:
     |                                            @::@:::@:::::@:: :::@@::@:#:
     |                      :@@@@@@@@@@@@@@@@@@@@:@::@:::@:::::@:: :::@@::@:#:
     |                      :@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                    :@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                    :@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                   :@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                   :@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |              :@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |          :::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |        :::::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |       ::::::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |       ::::::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
   0 +----------------------------------------------------------------------->Mi
     0                                                                   1.140

Et ici, nous voyons (très empiriquement et avec une confiance très élevée) que le compilateur a alloué 77 Ko de tas.

Pourquoi essayer si fort de n'utiliser que du tas? Parce que tous les objets partagés et les sections de texte qu'un processus utilise (dans cet exemple, le compilateur) ne sont pas terriblement intéressants. Ils sont des frais généraux constants pour un processus. En fait, les invocations ultérieures du processus sont presque gratuites.

Comparez et contrastez également les éléments suivants:

MMAP () un fichier de 1 Go. Votre VMSize sera de 1 + Go. Mais vous êtes résident, la taille définie ne sera que les parties du fichier dans lesquelles vous avez fait paginer (en déréférençant un pointeur sur cette région). Et si vous "lisez" l'intégralité du fichier, au moment où vous arrivez à la fin, le noyau peut avoir déjà paginé les débuts (c'est facile à faire car le noyau sait exactement comment/où remplacer ces pages s'il est à nouveau référencé ). Dans les deux cas, ni VMSize ni RSS ne sont un bon indicateur de votre "utilisation" de la mémoire. Vous n'avez rien fait de malloc ().

En revanche, Malloc () et touchez BEAUCOUP de mémoire - jusqu'à ce que votre mémoire soit échangée sur le disque. Ainsi, votre mémoire allouée dépasse désormais votre flux RSS. Ici, votre VMSize peut commencer à vous dire quelque chose (votre processus possède plus de mémoire que ce qui réside réellement dans votre RAM). Mais il est toujours difficile de faire la différence entre VM qui est des pages partagées et VM qui est des données échangées).

C'est là que valgrind/massif devient intéressant. Il vous montre ce que vous avez intentionnellement alloué (quel que soit l'état de vos pages).

4
Miles F. Bintz II

Essayez ceci: il vous donnera le total RAM réellement utilisé par tous les processus exécutés en Mo

ps -eo size,pid,user,command --sort -size | awk '
  { hr=$1/1024 ; printf("%13.2f Mb ",hr) } 
  { for ( x=4 ; x<=NF ; x++ ) { printf("%s ",$x) } print "" }
  ' | awk '{total=total + $1} END {print total}'
2
Vineeth