Che cos'è RSS e VSZ nella gestione della memoria Linux


Risposte:


499

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:


17
Credo RSS fa comprendere memoria da librerie collegate dinamicamente. Se si utilizzano 3 processi libxml2.so, la libreria condivisa verrà conteggiata in ciascuno dei loro RSS, quindi la somma dei loro RSS sarà maggiore della memoria effettiva utilizzata.
nfm,

1
È corretto. Ho risolto la mia risposta, grazie per l'heads up.
Jmh

Sono su Ubuntu 16.04 e c'è un processo Java con 1.2G RES e 4.5G VIRT che mostrano dal topcomando. Questo sistema non ha alcuno scambio, swapon --shownon 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 ...
Aaron Wang,

Non sono veramente sicuro. Dai un'occhiata a questa risposta sull'utilizzo della memoria virtuale Java: stackoverflow.com/a/561450/622115 . Versione breve: VSZ può includere spazio heap allocato e non utilizzato nonché file mappati in memoria.
Jmh

Grande. Aggiungi qualcosa. se malloc (100 KB), allora utilizza solo 1 KB. L'RSS è 1K e vsz è 100K, anche se qui non c'è scambio.
Keniee van,

53

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.


Ti dispiace fornire più informazioni di quanto l'abbreviazione rappresenti?
Pithikos,

10

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:

  • alloca più RAM della nostra memoria fisica con mmap
  • scrive un byte su ogni pagina per garantire che ciascuna di quelle pagine passi dalla memoria virtuale (VSZ) alla memoria effettivamente utilizzata (RSS)
  • controlla l'utilizzo della memoria del processo con uno dei metodi indicati in: Utilizzo della memoria del processo corrente in C

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

GitHub a monte .

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:

  • 0x1000000000 == 64GiB: 2x RAM fisica del mio computer di 32GiB
  • 0x200000000 == 8GiB: stampa la memoria ogni 8GiB, quindi dovremmo ottenere 4 stampe prima dell'incidente a circa 32GiB
  • 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ò allocare

Uscita 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:

  • La memoria virtuale VSZ rimane costante su printf '0x%X\n' 0x40009A4 KiB ~= 64GiB(i psvalori sono in KiB) dopo la mmap.
  • RSS "utilizzo della memoria reale" aumenta pigramente solo quando tocchiamo le pagine. Per esempio:
    • alla prima stampa, abbiamo extra_memory_committed 0, il che significa che non abbiamo ancora toccato alcuna pagina. RSS è un piccolo 1648 KiBche è stato allocato per l'avvio normale del programma come area di testo, globi, ecc.
    • sulla seconda stampa, abbiamo scritto per 8388608 KiB == 8GiBvalore di pagine. Di conseguenza, RSS è aumentato di esattamente 8GIB a8390256 KiB == 8388608 KiB + 1648 KiB
    • RSS continua ad aumentare con incrementi di 8GiB. L'ultima stampa mostra circa 24 GiB di memoria e prima che 32 GiB potessero essere stampati, il killer OOM ha ucciso il processo

Vedi anche: /unix/35129/need-explanation-on-resident-set-size-virtual-size

Registri killer OOM

I nostri dmesgcomandi 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.outeffettivamente 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 865ciò 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 è oomstato 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.


8

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.


Ti riferisci al libro "Linux Kernel Development" di Love?
benjimin

1

Non sono gestiti, ma misurati e possibilmente limitati (vedi getrlimitchiamata 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/mapse il relativo stato (incluso il consumo di memoria) tramitecat /proc/1234/status


1
Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il collegamento come riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. - Dalla recensione
Maak

Ho fornito un secondo link. Uno di questi rimarrà valido
Basile Starynkevitch
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.