Determinare correttamente l'utilizzo della memoria in Linux


63

Sono un po 'confuso su alcuni dei risultati che sto vedendo da ps e gratuitamente .

Sul mio server, questo è il risultato di 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

La mia comprensione di come Linux gestisce la memoria è che memorizzerà l'utilizzo del disco nella RAM, in modo che ogni accesso successivo sia più veloce. Credo che ciò sia indicato dalle colonne "memorizzate nella cache". Inoltre, vari buffer sono memorizzati nella RAM, indicato nella colonna "buffer".

Quindi, se ho capito bene, l'uso "effettivo" dovrebbe essere il valore "usato" di "- / + buffer / cache", o 561 in questo caso.

Quindi supponendo che tutto ciò sia corretto, la parte che mi lancia sono i risultati di ps aux.

La mia comprensione dei psrisultati è che la sesta colonna (RSS), rappresenta la dimensione in kilobyte che il processo utilizza per la memoria.

Quindi quando eseguo questo comando:

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

Il risultato non dovrebbe essere la colonna "usata" di "- / + buffer / cache" da free -m?

Quindi, come posso determinare correttamente l'utilizzo della memoria di un processo in Linux? Apparentemente la mia logica è imperfetta.


Questa domanda è piuttosto popolare e penso che dovrei condividere una risposta htopdell'autore a una domanda simile che ho avuto l'altro giorno ... Come calcolare l'utilizzo della memoria da / proc / meminfo (come htop)
tgogos

Risposte:


58

Questo esatto stessa domanda è stata posta sul serverfault proprio l'altro giorno :-)

Il sistema di memoria virtuale Linux non è così semplice. Non puoi semplicemente sommare tutti i campi RSS e ottenere il valore riportato usedda free. Ci sono molte ragioni per questo, ma colpirò un paio di quelli più grandi.

  • Quando un processo esegue il fork, sia il genitore che il figlio mostreranno lo stesso RSS. Comunque Linux impiega in copy-on-writemodo che entrambi i processi stiano realmente usando la stessa memoria. Solo quando uno dei processi modifica la memoria verrà effettivamente duplicata. Pertanto, il freenumero sarà inferiore alla topsomma RSS.

  • Il valore RSS non include la memoria condivisa. Poiché la memoria condivisa non è di proprietà di alcun processo, topnon la include in RSS. Quindi questo farà sì che il freenumero sia maggiore della topsomma RSS.


1
Questa è la migliore risposta che ho ottenuto su qualsiasi sito di scambio di stack fino ad oggi. Quindi, nello specifico, quello che volevo sapere. È così particolarmente preciso per la mia situazione perché ho a che fare con un programma che ho scritto forchette di processi, ma la maggior parte dell'impronta è nelle librerie che usano.
GoldenNewby,

Il problema con questa risposta è che il calcolo della somma di RSS e SHR spesso dà molto meno della memoria utilizzata. Ad esempio su un VPS che ho, la memoria utilizzata è di 380 MB mentre la somma di tutti gli RSS e SHR è di 90 MB.
user239558

2
@ user239558 Come ho detto nella risposta, ci sono molte ragioni per cui i numeri non si sommano, ne ho elencati solo 2. Ci sono molti altri numeri; cache, lastra, pagine enormi, ecc.
Patrick,

2
Probabilmente anni dopo la tua risposta, ho ancora (almeno) una confusione. Hai detto che il valore RSS non include la memoria condivisa, ma questa risposta affermava che "Include la memoria delle librerie condivise fintanto che le pagine di quelle librerie sono effettivamente in memoria". Ora non so a quale credere ... Forse mi sto perdendo alcune sottili differenze qui ...
Naitree,

1
@Naitree "shared libraries"! = "Memoria condivisa". la memoria condivisa è roba come shmgeto mmap. La formulazione intorno alla memoria è molto complicata. L'uso della parola sbagliata nel posto sbagliato può rovinare totalmente il significato di una frase.
Patrick,

30

Se stai cercando numeri di memoria che si sommano dai un'occhiata a smem :

smem è uno strumento in grado di fornire numerosi report sull'utilizzo della memoria su sistemi Linux. A differenza degli strumenti esistenti, smem può riportare dimensioni di set proporzionale (PSS), che è una rappresentazione più significativa della quantità di memoria utilizzata da librerie e applicazioni in un sistema di memoria virtuale.

Poiché ampie porzioni di memoria fisica sono in genere condivise tra più applicazioni, la misura standard dell'utilizzo della memoria nota come dimensione del set di residenti (RSS) sovrastimerà significativamente l'utilizzo della memoria. PSS invece misura la "quota equa" di ciascuna applicazione di ciascuna area condivisa per fornire una misura realistica.

Per esempio qui:

# 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 

Così PSSè la colonna interessante qui perché tiene conto della memoria condivisa.
Diversamente RSSè significativo aggiungerlo. Otteniamo un totale di 654 Mb per i processi relativi agli utenti qui.

L'output a livello di sistema racconta il resto:

# 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 

Quindi 1Gb di RAM totale = 654 Mb di processi di userland + 346Mb di kernel mem + 16Mb gratuiti
(dare o prendere qualche Mb)

Complessivamente circa la metà della memoria viene utilizzata per la cache (494 Mb).

Domanda bonus : che cos'è qui la cache userland vs cache kernel?


btw per qualcosa di visivo prova:

# smem  --pie=name

inserisci qui la descrizione dell'immagine


14

Uno strumento davvero valido è quello pmapche elenca l'utilizzo corrente della memoria per un determinato processo:

pmap -d PID

Per maggiori informazioni a riguardo vedi la pagina di manuale man pmape dai un'occhiata anche a 20 strumenti di monitoraggio del sistema Linux che ogni amministratore di sistema dovrebbe conoscere , che elencano i grandi strumenti che uso sempre per ottenere informazioni sulla mia macchina Linux.


È uno strumento piuttosto interessante, ma non risolve davvero il mio problema. Sto cercando di capire come determinare in modo efficace l'utilizzo della memoria "reale" sul server.
GoldenNewby,

3
@GoldenNewby Non esiste un utilizzo “effettivo” della memoria di un processo. L'utilizzo effettivo della memoria del sistema è ciò che freeti dice.
Gilles 'SO-smetti di essere malvagio' il

pmap -x PIDinclude anche una colonna RSS che è spesso molto utile per avere un'idea della topprovenienza della somma RSS di un processo (come osservato ad es. via ).
maxschlepzig,

10

Esegui in alto, premi hper chiedere aiuto, quindi fper aggiungere campi. puoi aggiungere i seguenti campi:

  • RSS quantità di memoria fisica utilizzata dall'applicazione
  • CODE quantità totale di memoria utilizzata dal codice eseguibile del processo
  • DATA - quantità totale di memoria (kb) dedicata ai dati e allo stack di un processo

Tra questi 3 dovresti avere risultati abbastanza precisi. È inoltre possibile utilizzare sostituti più dettagliati per i migliori che consiglio htopo atop.

Modifica: quasi dimenticato se vuoi informazioni molto dettagliate. Trova il PID e cat il seguente file.

PID=123

cat /proc/123/status

Modifica 2: se riesci a trovarlo o ad averlo nel libro:

Ottimizzazione delle prestazioni di Linux: una guida pratica agli strumenti per le prestazioni di Linux

-ha una sezione Capitolo 5: Strumenti per le prestazioni: memoria specifica del processo -ha molte più informazioni di quante tu possa desiderare.


Bene, per impostazione predefinita, la parte superiore ha la dimensione RSS del processo. Top dà risultati identici come "ps aux" nel mio esempio. La mia domanda è: com'è possibile che l'RSS combinato di tutti i processi sia molto più elevato dell'utilizzo della memoria "attiva" sull'intero server?
GoldenNewby,

5

psti dà la quantità di memoria utilizzata da ogni processo. Parte di quella memoria sono file mmapped, che contano nella cache. Parte di quella memoria (in particolare il codice) è condivisa con altri processi, quindi se si sommano i valori RSS viene conteggiato più volte.

Non esiste una risposta corretta a "quanta memoria utilizza questo processo?", Perché non dipende solo dal processo, ma dipende anche dall'ambiente. Esistono molti valori diversi che potresti chiamare "utilizzo della memoria" del processo e non corrispondono o si sommano perché contano cose diverse.


4

Come altri hanno giustamente sottolineato, è difficile ottenere un handle sulla memoria effettiva utilizzata da un processo, cosa con le aree condivise, i file mmap e quant'altro.

Se sei uno sperimentatore, puoi eseguire valgrind e massiccio . Questo potrebbe diventare un po 'pesante per l'utente occasionale, ma ti verrà un'idea del comportamento della memoria di un'applicazione nel tempo. Se un'applicazione malloc () è esattamente ciò di cui ha bisogno, questo ti darà una buona rappresentazione dell'utilizzo reale della memoria dinamica di un processo. Ma questo esperimento può essere "avvelenato".

A complicare le cose, Linux ti consente di sovraccaricare la tua memoria. Quando malloc () memoria, dichiari il tuo intento di consumare memoria. Ma l'allocazione non avviene realmente finché non si scrive un byte in una nuova pagina della "RAM" allocata. Puoi dimostrarlo scrivendo ed eseguendo un piccolo programma C in questo modo:

// 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 $!

Eseguilo su una macchina con meno di 16 GB di RAM e, voilà !, hai appena ottenuto 16 GB di memoria! (no, non proprio).

Notare in topte "VIRT" come 16.004G ma% MEM è 0.0

Esegui di nuovo con valgrind:

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

E il massiccio dice "somma di tutte le risorse () = 16 GB". Quindi non è molto interessante.

MA, se lo esegui su un processo sano :

# 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

E qui vediamo (molto empiricamente e con la massima fiducia) che il compilatore ha allocato 77 KB di heap.

Perché provare così tanto per ottenere solo un utilizzo dell'heap? Perché tutti gli oggetti condivisi e le sezioni di testo utilizzate da un processo (in questo esempio il compilatore) non sono tremendamente interessanti. Sono costanti costi generali per un processo. In effetti, le successive invocazioni del processo arrivano quasi per "libero".

Inoltre, confronta e confronta quanto segue:

MMAP () un file da 1 GB. Il tuo VMSize sarà 1 + GB. Ma sei Resident Set Size saranno solo le parti del file in cui hai fatto il paging (dereferenziando un puntatore a quella regione). E se "leggi" l'intero file allora, quando arriverai alla fine, il kernel potrebbe aver già eseguito il paging degli inizi (questo è facile da fare perché il kernel sa esattamente come / dove sostituire quelle pagine se nuovamente referenziato ). In entrambi i casi, né VMSize né RSS sono un buon indicatore del "utilizzo" della memoria. In realtà non hai malloc () ed ed nulla.

Al contrario, Malloc () e tocca MOLTA memoria - fino a quando la memoria non viene scambiata su disco. Quindi la tua memoria allocata ora supera il tuo RSS. Qui, il tuo VMSize potrebbe iniziare a dirti qualcosa (il tuo processo possiede più memoria di ciò che risiede effettivamente nella RAM). Ma è ancora difficile distinguere tra VM che è pagine condivise e VM che è scambiata dati.

Qui è dove valgrind / massiccio diventa interessante. Ti mostra ciò che hai allocato intenzionalmente (indipendentemente dallo stato delle tue pagine).


Ho una domanda per te. Ho un processo che mlock () s tutti i suoi file mmap. Esiste un modo per determinare quanta parte di questa memoria è attivamente utilizzata - in che misura è stata letta o scritta in, diciamo, negli ultimi due minuti?
Michael Martinez,

2

Prova questo: ti darà la RAM totale effettivamente utilizzata da tutto il processo in esecuzione in MB

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}'

Il sizereport di psha poca relazione con l'effettivo utilizzo della memoria. È la dimensione virtuale di ogni processo che non è necessariamente allocata memoria. Inoltre non include alcuni segmenti allocati.
Matt

-2

Ti mostrerà la quantità di memoria dell'utente da parte degli utenti.

#!/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

-3

Utilizzare questo comando per trovare l'utilizzo della memoria in%.

Memoria utilizzata:

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

memoria libera

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

3
Errr, questo non farà nulla. grepsiederà lì in attesa di input.
Mattdm,

1
Questo avrebbe dovuto esserefree -m | grep Mem | awk '{print $3/$2 * 100.0}'
vjangus,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.