Détermination correcte de l'utilisation de la mémoire sous Linux

63

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

Sur mon serveur, ceci 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 manière dont Linux gère la mémoire consiste à stocker l’utilisation du disque dans la RAM, de sorte que chaque accès ultérieur soit plus rapide. Je crois que cela est indiqué par les colonnes "mises 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 supposée être la valeur "utilisée" de "- / + buffers / cache", ou 561 dans ce cas.

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

D'après ce que je comprends des psrésultats, la 6ème colonne (RSS) représente la taille en kilo-octets utilisée par le processus pour la mémoire.

Alors quand je lance 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ée" de "- / + buffers / cache" from free -m?

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

GoldenNewby
la source
Cette question est très populaire et je pense que je devrais partager une réponse de l' htopauteur à une question similaire que j'avais posée l'autre jour ... Comment calculer l'utilisation de la mémoire à partir de / proc / meminfo (comme htop)
tgogos

Réponses:

58

Ce exact même question a été posée sur serverfault l'autre jour :-)

Le système de mémoire virtuelle Linux n'est pas si simple. Vous ne pouvez pas simplement additionner tous les champs RSS et obtenir la valeur indiquée usedpar free. Il y a de nombreuses raisons à cela, mais je vais aborder quelques-unes des plus importantes.

  • Lorsqu'un processus se divise, le parent et l'enfant s'affichent avec le même flux RSS. Cependant, Linux utilise copy-on-writepour que les deux processus utilisent vraiment la même mémoire. Ce n’est que lorsque l’un des processus modifie la mémoire que celle-ci sera réellement dupliquée. Ainsi, le freenombre sera inférieur à la topsomme RSS.

  • La valeur RSS n'inclut pas la mémoire partagée. Parce que la mémoire partagée n'appartient à aucun processus, topne l'incluez pas dans RSS. Ainsi, le freenombre sera supérieur à la topsomme RSS.

Patrick
la source
1
C'est la meilleure réponse que j'ai eue sur n'importe quel site d'échange de piles à ce jour. Donc, précisément ce que je voulais savoir. C'est particulièrement vrai pour ma situation, car je traite d'un programme que j'ai écrit en tant que processus, mais la majeure partie de l'empreinte réside dans les bibliothèques qu'ils utilisent.
GoldenNewby
Le problème avec cette réponse est que le calcul de la somme de RSS et de SHR donne souvent beaucoup moins que la mémoire utilisée. Par exemple, sur un VPS que j'ai, la mémoire utilisée est de 380 Mo alors que la somme de tous les flux RSS et SHR est de 90 Mo.
user239558
2
@ user239558 Comme je l'ai mentionné dans la réponse, il y a plusieurs raisons pour lesquelles les chiffres ne concordent pas, je n'en ai répertorié que deux. Il y a beaucoup d'autres chiffres; cache, dalle, énormes pages, etc.
Patrick
2
Probablement des années plus tard, après avoir répondu à cette question, il me reste encore (au moins) une confusion. Vous avez dit que la valeur RSS n'incluait pas la mémoire partagée, mais cette réponse indiquait qu '"elle incluait la mémoire des bibliothèques partagées tant que les pages de ces bibliothèques étaient réellement en mémoire". Maintenant, je ne sais pas lequel croire ... Peut-être me manque-t-il quelques différences subtiles ici ...
Naitree,
1
@Naitree "bibliothèques partagées"! = "Mémoire partagée". la mémoire partagée est un truc comme shmgetou mmap. La formulation autour de la mémoire est très délicate. Utiliser le mauvais mot au mauvais endroit peut totalement bousiller le sens d'une phrase.
Patrick le
30

Si vous cherchez des nombres de mémoire qui s'additionnent jetez un coup d'oeil à smem :

smem est un outil capable de générer 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, appelée taille du jeu résident (RSS), surestime considérablement l'utilisation de la mémoire. PSS mesure plutôt la "juste part" 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 

Il en PSSva de même de la colonne intéressante car elle prend en compte la mémoire partagée.
Contrairement à RSScela, il est significatif de l'additionner. Nous obtenons un total de 654 Mo pour les processus utilisateur ici.

La sortie globale du système indique 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 de RAM au total = 654 Mo de processus utilisateur + 346 Mo de mémoire du noyau + 16 Mo d' espace libre
(à quelques Mo près)

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

Question bonus : qu'est-ce que le cache utilisateur et le cache noyau ici?


btw pour quelque chose de visuel essayez:

# smem  --pie=name

entrez la description de l'image ici

citron
la source
14

Un très bon outil est la pmapliste de l’utilisation actuelle de la mémoire pour un processus donné:

pmap -d PID

Pour plus d'informations à ce sujet, consultez la page de manuel man pmapet consultez également 20 outils de surveillance du système Linux que chaque administrateur système devrait connaître , liste des outils que j'utilise toujours pour obtenir des informations sur ma machine Linux.

ByteNudger
la source
C'est un outil plutôt cool, mais cela ne résout pas vraiment mon problème. J'essaie de comprendre comment déterminer efficacement l'utilisation "réelle" de la mémoire sur le serveur.
GoldenNewby
3
@GoldenNewby Il n'y a rien de tel que l'utilisation «réelle» de la mémoire d'un processus. C'est l'utilisation réelle de la mémoire du système qui freevous indique.
Gilles 'SO- arrête d'être méchant'
pmap -x PIDinclut également une colonne RSS qui est souvent très utile pour avoir une idée de la somme RSS d’un processus (comme observé par exemple via topprovient).
maxschlepzig
10

Courrez en haut, appuyez hpour obtenir de l'aide puis fpour 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 (kb) 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 top que je recommande htopou 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 sur les outils de performance Linux

-a une section Chapitre 5: Outils de performance: Mémoire spécifique au processus -elle contient beaucoup plus d'informations que vous ne voudriez jamais.

2bc
la source
Eh bien top par défaut a la taille RSS du processus. Top donne les mêmes résultats que "ps aux" dans mon exemple. Ma question est la suivante: comment se fait-il que le RSS combiné de tous les processus soit beaucoup plus élevé que l'utilisation de la mémoire "active" sur l'ensemble du serveur?
GoldenNewby
5

psvous donne la quantité de mémoire utilisée par chaque processus. Une partie de cette mémoire est constituée de fichiers mappés, qui comptent sous cache. Une partie de cette mémoire (en particulier du code) est partagée avec d'autres processus. Par conséquent, 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 du processus seul, il dépend également de l'environnement. Il existe de nombreuses valeurs que vous pouvez appeler «utilisation de la mémoire» du processus. Elles ne correspondent ni ne s'additionnent car elles comptent des éléments différents.

Gilles, arrête de faire le mal
la source
4

Comme d'autres l'ont souligné à juste titre, il est difficile de connaître la mémoire réellement utilisée par un processus, les régions partagées, les fichiers mmap'ed, etc.

Si vous êtes un expérimentateur, vous pouvez exécuter valgrind et massif . Cela peut paraître 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 () correspond 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 malloc (), vous indiquez 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 vous 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 cette application sur une machine disposant de moins de 16 Go de RAM et, voila!, Vous venez de bénéficier de 16 Go de mémoire! (non, pas vraiment).

Notez que topvous voyez "VIRT" comme 16.004G mais% MEM est 0.0

Exécutez ceci à nouveau avec valgrind:

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

Et massif dit "somme de tous les allocs () = 16 Go". Donc ce n'est 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 nous voyons ici (très empiriquement et avec une très grande confiance) que le compilateur a alloué 77 Ko de tas.

Pourquoi essayer si fort d’obtenir une utilisation juste du tas? Parce que tous les objets partagés et les sections de texte utilisés par un processus (dans cet exemple, le compilateur) ne sont pas très intéressants. Ils sont des frais généraux constants pour un processus. En fait, les invocations ultérieures du processus sont presque "gratuites".

En outre, comparez les éléments suivants:

MMAP () un fichier de 1 Go. Votre VMSize sera 1 + GB. Mais votre taille de groupe de résidents ne sera que les parties du fichier dans lesquelles vous avez paginé (en supprimant la référence d'un pointeur vers cette région). Et si vous "lisez" l'intégralité du fichier, le noyau aura peut-être déjà commencé à paginer au début (c'est facile à faire, car le noyau sait exactement comment et où remplacer ces pages si elles sont à nouveau déréférencées ). Dans les deux cas, ni VMSize ni RSS ne sont un bon indicateur de votre "utilisation" en mémoire. Vous n'avez rien fait de malloc ().

En revanche, Malloc () et appuyez sur BEAUCOUP de mémoire - jusqu'à ce que votre mémoire soit échangée sur le disque. Donc, votre mémoire allouée dépasse maintenant votre RSS. Ici, votre VMSize pourrait commencer à vous dire quelque chose (votre processus possède plus de mémoire que ce qui se trouve réellement dans votre RAM). Cependant, il est toujours difficile de faire la distinction entre une machine virtuelle composée de pages partagées et une machine virtuelle échangeant des donné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).

Miles F. Bintz II
la source
J'ai une question pour vous. J'ai un processus qui mlock () s tous ses fichiers mmap'ed. Existe-t-il un moyen de déterminer quelle quantité de cette mémoire est activement utilisée - dans quelle mesure a-t-elle été lue ou écrite dans, disons, la dernière minute ou deux?
Michael Martinez
2

Essayez ceci: cela vous donnera la quantité totale de RAM réellement utilisée par tous les processus en cours d'exécution 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}'
Vineeth
la source
Le sizesignalé par psa peu de relation avec l'utilisation réelle de la mémoire. C'est la taille virtuelle de chaque processus qui n'est pas nécessairement allouée en mémoire. Il n'inclut pas non plus certains segments alloués.
Matt
-2

Il va vous montrer combien de mémoire utilisateur par les utilisateurs ..

#!/bin/bash
total_mem=0

printf "%-10s%-10s\n" User MemUsage

while read u m
do
        [[ $old_user != $u ]] && {  printf "%-10s%-0.1f\n" $old_user $total_mem;
                                    total_mem=0; }
        total_mem="$(echo $m + $total_mem | bc)"
        old_user=$u

done < <(ps --no-headers -eo user,%mem| sort -k1)

#EOF
Vinood NK Maheshwari
la source
-3

Utilisez cette commande pour rechercher une utilisation de la mémoire en%.

Mémoire utilisée:

grep Mem | awk '{print $3/$2 * 100.0}'

mémoire libre

grep Mem | awk '{print $4/$2 * 100.0}'
Arjun K Mukundan
la source
3
Euh, ça ne fera rien. grepje resterai juste là à attendre vos commentaires.
Mattdm
1
Cela aurait dû êtrefree -m | grep Mem | awk '{print $3/$2 * 100.0}'
vjangus