Risposte:
RSS è la dimensione del set di residenti e viene utilizzata per mostrare quanta memoria è allocata a quel processo ed è nella RAM. Non include la memoria che viene sostituita. Include la memoria delle librerie condivise purché le pagine di tali librerie siano effettivamente in memoria. Include tutta la memoria dello stack e dell'heap.
VSZ è la dimensione della memoria virtuale. Include tutta la memoria a cui il processo può accedere, inclusa la memoria che viene scambiata, la memoria allocata, ma non utilizzata, e la memoria proveniente dalle librerie condivise.
Quindi, se il processo A ha un file binario da 500 K ed è collegato a 2500 K di librerie condivise, ha 200 K di allocazioni stack / heap di cui 100 K sono effettivamente in memoria (il resto è scambiato o inutilizzato) e ha effettivamente caricato solo 1000 K delle librerie condivise e 400K del proprio binario quindi:
RSS: 400K + 1000K + 100K = 1500K
VSZ: 500K + 2500K + 200K = 3200K
Poiché parte della memoria è condivisa, molti processi potrebbero usarla, quindi se si sommano tutti i valori RSS si può facilmente finire con più spazio di quello che ha il sistema.
Anche la memoria allocata potrebbe non essere in RSS fino a quando non viene effettivamente utilizzata dal programma. Quindi, se il tuo programma ha allocato un mucchio di memoria in anticipo, quindi lo usa nel tempo, potresti vedere l'RSS che sale e il VSZ rimane lo stesso.
C'è anche PSS (dimensioni proporzionali impostate). Questa è una misura più recente che tiene traccia della memoria condivisa come proporzione utilizzata dal processo corrente. Quindi, se c'erano due processi che utilizzavano la stessa libreria condivisa di prima:
PSS: 400K + (1000K/2) + 100K = 400K + 500K + 100K = 1000K
I thread condividono tutti lo stesso spazio degli indirizzi, quindi RSS, VSZ e PSS per ciascun thread sono identici a tutti gli altri thread nel processo. Usa ps o top per visualizzare queste informazioni in linux / unix.
C'è molto più di questo, per saperne di più controlla i seguenti riferimenti:
Vedi anche:
libxml2.so
, la libreria condivisa verrà conteggiata in ciascuno dei loro RSS, quindi la somma dei loro RSS sarà maggiore della memoria effettiva utilizzata.
top
comando. Questo sistema non ha alcuno scambio, swapon --show
non restituisce nulla. Come lo spieghi? Se vsz è swap + librerie condivise, in questo caso le librerie condivise sono superiori a 3.3G? È possibile? Solo molto confuso ...
RSS è Resident Set Size (memoria fisica residente - attualmente occupa spazio nella memoria fisica della macchina) e VSZ è Virtual Memory Size (spazio indirizzo allocato - questo ha indirizzi allocati nella mappa di memoria del processo, ma non c'è necessariamente nessuno memoria reale dietro tutto adesso).
Si noti che in questi giorni di macchine virtuali ordinarie, la memoria fisica dal punto di vista della macchina potrebbe non essere realmente memoria fisica effettiva.
Esempio eseguibile minimo
Affinché ciò abbia un senso, è necessario comprendere le basi del paging: come funziona il paging x86? e in particolare che il sistema operativo può allocare memoria virtuale tramite tabelle di pagine / tenuta della sua memoria interna (memoria virtuale VSZ) prima che abbia effettivamente una memoria di supporto su RAM o disco (memoria residente RSS).
Ora per osservare questo in azione, creiamo un programma che:
mmap
main.c
#define _GNU_SOURCE
#include <assert.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
typedef struct {
unsigned long size,resident,share,text,lib,data,dt;
} ProcStatm;
/* /programming/1558402/memory-usage-of-current-process-in-c/7212248#7212248 */
void ProcStat_init(ProcStatm *result) {
const char* statm_path = "/proc/self/statm";
FILE *f = fopen(statm_path, "r");
if(!f) {
perror(statm_path);
abort();
}
if(7 != fscanf(
f,
"%lu %lu %lu %lu %lu %lu %lu",
&(result->size),
&(result->resident),
&(result->share),
&(result->text),
&(result->lib),
&(result->data),
&(result->dt)
)) {
perror(statm_path);
abort();
}
fclose(f);
}
int main(int argc, char **argv) {
ProcStatm proc_statm;
char *base, *p;
char system_cmd[1024];
long page_size;
size_t i, nbytes, print_interval, bytes_since_last_print;
int snprintf_return;
/* Decide how many ints to allocate. */
if (argc < 2) {
nbytes = 0x10000;
} else {
nbytes = strtoull(argv[1], NULL, 0);
}
if (argc < 3) {
print_interval = 0x1000;
} else {
print_interval = strtoull(argv[2], NULL, 0);
}
page_size = sysconf(_SC_PAGESIZE);
/* Allocate the memory. */
base = mmap(
NULL,
nbytes,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS,
-1,
0
);
if (base == MAP_FAILED) {
perror("mmap");
exit(EXIT_FAILURE);
}
/* Write to all the allocated pages. */
i = 0;
p = base;
bytes_since_last_print = 0;
/* Produce the ps command that lists only our VSZ and RSS. */
snprintf_return = snprintf(
system_cmd,
sizeof(system_cmd),
"ps -o pid,vsz,rss | awk '{if (NR == 1 || $1 == \"%ju\") print}'",
(uintmax_t)getpid()
);
assert(snprintf_return >= 0);
assert((size_t)snprintf_return < sizeof(system_cmd));
bytes_since_last_print = print_interval;
do {
/* Modify a byte in the page. */
*p = i;
p += page_size;
bytes_since_last_print += page_size;
/* Print process memory usage every print_interval bytes.
* We count memory using a few techniques from:
* /programming/1558402/memory-usage-of-current-process-in-c */
if (bytes_since_last_print > print_interval) {
bytes_since_last_print -= print_interval;
printf("extra_memory_committed %lu KiB\n", (i * page_size) / 1024);
ProcStat_init(&proc_statm);
/* Check /proc/self/statm */
printf(
"/proc/self/statm size resident %lu %lu KiB\n",
(proc_statm.size * page_size) / 1024,
(proc_statm.resident * page_size) / 1024
);
/* Check ps. */
puts(system_cmd);
system(system_cmd);
puts("");
}
i++;
} while (p < base + nbytes);
/* Cleanup. */
munmap(base, nbytes);
return EXIT_SUCCESS;
}
Compila ed esegui:
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
echo 1 | sudo tee /proc/sys/vm/overcommit_memory
sudo dmesg -c
./main.out 0x1000000000 0x200000000
echo $?
sudo dmesg
dove:
echo 1 | sudo tee /proc/sys/vm/overcommit_memory
: richiesto per Linux per consentirci di effettuare una chiamata mmap più grande della RAM fisica: memoria massima che malloc può allocareUscita del programma:
extra_memory_committed 0 KiB
/proc/self/statm size resident 67111332 768 KiB
ps -o pid,vsz,rss | awk '{if (NR == 1 || $1 == "29827") print}'
PID VSZ RSS
29827 67111332 1648
extra_memory_committed 8388608 KiB
/proc/self/statm size resident 67111332 8390244 KiB
ps -o pid,vsz,rss | awk '{if (NR == 1 || $1 == "29827") print}'
PID VSZ RSS
29827 67111332 8390256
extra_memory_committed 16777216 KiB
/proc/self/statm size resident 67111332 16778852 KiB
ps -o pid,vsz,rss | awk '{if (NR == 1 || $1 == "29827") print}'
PID VSZ RSS
29827 67111332 16778864
extra_memory_committed 25165824 KiB
/proc/self/statm size resident 67111332 25167460 KiB
ps -o pid,vsz,rss | awk '{if (NR == 1 || $1 == "29827") print}'
PID VSZ RSS
29827 67111332 25167472
Killed
Stato di uscita:
137
che secondo la regola 128 + numero di segnale significa che abbiamo ottenuto il numero di segnale 9
, che man 7 signal
è SIGKILL , che viene inviato dal killer di memoria insufficiente di Linux .
Interpretazione dell'output:
printf '0x%X\n' 0x40009A4 KiB ~= 64GiB
(i ps
valori sono in KiB) dopo la mmap.extra_memory_committed 0
, il che significa che non abbiamo ancora toccato alcuna pagina. RSS è un piccolo 1648 KiB
che è stato allocato per l'avvio normale del programma come area di testo, globi, ecc.8388608 KiB == 8GiB
valore di pagine. Di conseguenza, RSS è aumentato di esattamente 8GIB a8390256 KiB == 8388608 KiB + 1648 KiB
Vedi anche: /unix/35129/need-explanation-on-resident-set-size-virtual-size
Registri killer OOM
I nostri dmesg
comandi hanno mostrato i registri killer OOM.
Un'interpretazione esatta di questi è stata chiesta a:
La prima riga del registro era:
[ 7283.479087] mongod invoked oom-killer: gfp_mask=0x6200ca(GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=0
Quindi vediamo che è interessante notare che è stato il demone MongoDB che gira sempre sul mio laptop in background a innescare il killer OOM, presumibilmente quando il povero cercava di allocare un po 'di memoria.
Tuttavia, il killer OOM non uccide necessariamente chi lo ha svegliato.
Dopo l'invocazione, il kernel stampa una tabella o processi tra cui oom_score
:
[ 7283.479292] [ pid ] uid tgid total_vm rss pgtables_bytes swapents oom_score_adj name
[ 7283.479303] [ 496] 0 496 16126 6 172032 484 0 systemd-journal
[ 7283.479306] [ 505] 0 505 1309 0 45056 52 0 blkmapd
[ 7283.479309] [ 513] 0 513 19757 0 57344 55 0 lvmetad
[ 7283.479312] [ 516] 0 516 4681 1 61440 444 -1000 systemd-udevd
e più avanti vediamo che il nostro piccolo è stato main.out
effettivamente ucciso sulla precedente invocazione:
[ 7283.479871] Out of memory: Kill process 15665 (main.out) score 865 or sacrifice child
[ 7283.479879] Killed process 15665 (main.out) total-vm:67111332kB, anon-rss:92kB, file-rss:4kB, shmem-rss:30080832kB
[ 7283.479951] oom_reaper: reaped process 15665 (main.out), now anon-rss:0kB, file-rss:0kB, shmem-rss:30080832kB
Questo registro menziona score 865
ciò che quel processo aveva, presumibilmente il punteggio killer OOM più alto (peggiore) come menzionato su: /unix/153585/how-does-the-oom-killer-decide-which- processo-to-kill-prima
Inoltre, a quanto pare, tutto apparentemente è accaduto così in fretta che prima che la memoria liberata fosse spiegata, il processo è oom
stato risvegliato di nuovo DeadlineMonitor
:
[ 7283.481043] DeadlineMonitor invoked oom-killer: gfp_mask=0x6200ca(GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=0
e questa volta che ha ucciso qualche processo di Chromium, che di solito è il mio normale maiale della memoria del mio computer:
[ 7283.481773] Out of memory: Kill process 11786 (chromium-browse) score 306 or sacrifice child
[ 7283.481833] Killed process 11786 (chromium-browse) total-vm:1813576kB, anon-rss:208804kB, file-rss:0kB, shmem-rss:8380kB
[ 7283.497847] oom_reaper: reaped process 11786 (chromium-browse), now anon-rss:0kB, file-rss:0kB, shmem-rss:8044kB
Testato in Ubuntu 19.04, kernel Linux 5.0.0.
Penso che sia già stato detto molto su RSS vs VSZ. Dal punto di vista dell'amministratore / programmatore / utente, quando progetto / codifico applicazioni sono più preoccupato per la RSZ, (memoria residente), mentre e quando continui a estrarre sempre più variabili (ammucchiate) vedrai questo valore aumentare. Prova un semplice programma per creare l'allocazione dello spazio basata su malloc in loop e assicurati di riempire i dati in quello spazio malloc. RSS continua a salire. Per quanto riguarda VSZ, è più la mappatura della memoria virtuale che linux fa, e una delle sue caratteristiche principali deriva dai concetti del sistema operativo convenzionale. La gestione di VSZ è gestita dalla gestione della memoria virtuale del kernel, per maggiori informazioni su VSZ, consultare la descrizione di Robert Love su mm_struct e vm_struct, che fanno parte della struttura di dati di base task_struct nel kernel.
Non sono gestiti, ma misurati e possibilmente limitati (vedi getrlimit
chiamata di sistema, anche su getrlimit (2) ).
RSS indica la dimensione del set di residenti (la parte dello spazio degli indirizzi virtuale che si trova nella RAM).
È possibile eseguire una query nello spazio di indirizzi virtuale del processo 1234 utilizzando proc (5) con cat /proc/1234/maps
e il relativo stato (incluso il consumo di memoria) tramitecat /proc/1234/status