Was ist RSS und VSZ in der Linux-Speicherverwaltung?

331

Was sind RSS und VSZ in der Linux-Speicherverwaltung? Wie können in einer Multithread-Umgebung beide verwaltet und verfolgt werden?

Tuban
quelle
Mögliches Duplikat von Understanding the Linux Oom-Killer Logs
Msangel

Antworten:

498

RSS ist die Resident Set Size und wird verwendet, um anzuzeigen, wie viel Speicher diesem Prozess zugewiesen ist und sich im RAM befindet. Es enthält keinen ausgelagerten Speicher. Es enthält Speicher aus gemeinsam genutzten Bibliotheken, solange sich die Seiten aus diesen Bibliotheken tatsächlich im Speicher befinden. Es enthält den gesamten Stapel- und Heapspeicher.

VSZ ist die Größe des virtuellen Speichers. Es enthält den gesamten Speicher, auf den der Prozess zugreifen kann, einschließlich des ausgelagerten Speichers, des zugewiesenen, aber nicht verwendeten Speichers und des aus gemeinsam genutzten Bibliotheken stammenden Speichers.

Wenn also Prozess A über eine 500-KB-Binärdatei verfügt und mit 2500.000 gemeinsam genutzten Bibliotheken verknüpft ist, über 200 KB Stapel- / Heap-Zuweisungen verfügt, von denen 100 KB tatsächlich im Speicher sind (Rest wird ausgetauscht oder nicht verwendet), und nur 1000 KB der gemeinsam genutzten Bibliotheken geladen und 400K seiner eigenen Binärdatei dann:

RSS: 400K + 1000K + 100K = 1500K
VSZ: 500K + 2500K + 200K = 3200K

Da ein Teil des Speichers gemeinsam genutzt wird, wird er möglicherweise von vielen Prozessen verwendet. Wenn Sie also alle RSS-Werte addieren, erhalten Sie leicht mehr Speicherplatz als Ihr System.

Der zugewiesene Speicher befindet sich möglicherweise auch nicht in RSS, bis er tatsächlich vom Programm verwendet wird. Wenn Ihr Programm also im Voraus eine Menge Speicher zugewiesen hat und diese dann im Laufe der Zeit verwendet, können Sie sehen, dass RSS steigt und VSZ gleich bleibt.

Es gibt auch PSS (Proportional Set Size). Dies ist eine neuere Kennzahl, die den gemeinsam genutzten Speicher als Anteil verfolgt, der vom aktuellen Prozess verwendet wird. Wenn also zwei Prozesse dieselbe gemeinsame Bibliothek von zuvor verwenden:

PSS: 400K + (1000K/2) + 100K = 400K + 500K + 100K = 1000K

Alle Threads haben denselben Adressraum, sodass RSS, VSZ und PSS für jeden Thread mit allen anderen Threads im Prozess identisch sind. Verwenden Sie ps oder top, um diese Informationen unter Linux / Unix anzuzeigen.

Es gibt viel mehr als das, um mehr zu erfahren, überprüfen Sie die folgenden Referenzen:

Siehe auch:

jmh
quelle
17
Ich glaube, RSS enthält Speicher aus dynamisch verknüpften Bibliotheken. Wenn 3 Prozesse verwendet werden libxml2.so, wird die gemeinsam genutzte Bibliothek in jedem ihrer RSS-Dateien gezählt, sodass die Summe ihrer RSS-Dateien höher ist als der tatsächlich verwendete Speicher.
NFM
1
Das ist richtig. Ich habe meine Antwort korrigiert, danke für die Hinweise.
jmh
Ich bin auf Ubuntu 16.04 und es gibt einen Java-Prozess mit 1.2G RES und 4.5G VIRT, der vom topBefehl angezeigt wird . Dieses System hat keinen Swap, swapon --showgibt nichts zurück. Wie erklären Sie das? Wenn vsz swap + gemeinsam genutzte Bibliotheken ist, sind in diesem Fall gemeinsam genutzte Bibliotheken älter als 3,3 G? Ist es möglich? Nur wirklich verwirrt ...
Aaron Wang
Ich bin mir nicht wirklich sicher. Sehen Sie sich diese Antwort zur Nutzung des virtuellen Java-Speichers an: stackoverflow.com/a/561450/622115 . Kurzversion: VSZ kann Heap-Speicherplatz enthalten, der zugewiesen und nicht verwendet wird, sowie Dateien mit Speicherzuordnung.
jmh
Großartig. Füge einfach etwas hinzu. Wenn Sie malloc (100KB), dann verwenden Sie tatsächlich nur 1KB. Der RSS ist 1K und vsz ist 100K, auch wenn hier kein Swap stattfindet.
Keniee van
53

RSS ist die Größe des residenten Satzes (physisch residenter Speicher - dieser belegt derzeit Speicherplatz im physischen Speicher des Computers), und VSZ ist die Größe des virtuellen Speichers (zugewiesener Adressraum - hier sind Adressen in der Speicherzuordnung des Prozesses zugeordnet, es sind jedoch nicht unbedingt Adressen vorhanden aktuelles Gedächtnis dahinter).

Beachten Sie, dass in diesen Tagen alltäglicher virtueller Maschinen der physische Speicher aus Sicht der Maschine möglicherweise nicht wirklich der tatsächliche physische Speicher ist.

caf
quelle
Möchten Sie mehr Informationen bereitstellen, als die Abkürzung bedeutet?
Pithikos
10

Minimal lauffähiges Beispiel

Damit dies sinnvoll ist, müssen Sie die Grundlagen des Paging verstehen: Wie funktioniert x86-Paging?und insbesondere, dass das Betriebssystem virtuellen Speicher über Seitentabellen / seine interne Speicherbuchhaltung (virtueller VSZ-Speicher) zuweisen kann, bevor es tatsächlich einen Sicherungsspeicher auf RAM oder Festplatte hat (RSS-residenter Speicher).

Um dies in Aktion zu beobachten, erstellen wir ein Programm, das:

  • weist mehr RAM zu als unser physischer Speicher mit mmap
  • schreibt ein Byte auf jede Seite, um sicherzustellen, dass jede dieser Seiten vom virtuellen Nur-Speicher (VSZ) zum tatsächlich verwendeten Speicher (RSS) wechselt.
  • Überprüft die Speichernutzung des Prozesses mit einer der folgenden Methoden: Speichernutzung des aktuellen Prozesses in C.

Haupt 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 stromaufwärts .

Kompilieren und ausführen:

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

wo:

  • 0x1000000000 == 64 GB: 2x physischer RAM meines Computers von 32 GB
  • 0x200000000 == 8 GB: Drucken Sie den Speicher alle 8 GB, daher sollten wir vor dem Absturz 4 Ausdrucke bei etwa 32 GB erhalten
  • echo 1 | sudo tee /proc/sys/vm/overcommit_memory: Erforderlich für Linux, damit wir einen mmap-Aufruf ausführen können, der größer als der physische RAM ist: Maximaler Speicher, den malloc zuweisen kann

Programmausgabe:

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

Ausgangsstatus:

137

die von den 128 + Signalnummer Regel Mitteln haben wir Signalnummer 9, die man 7 signalsagt , ist SIGKILL , die von der Linux gesendet wird , out-of-Memory - Killer .

Ausgangsinterpretation:

  • Der virtuelle VSZ-Speicher bleibt nach der mmap konstant printf '0x%X\n' 0x40009A4 KiB ~= 64GiB( psWerte sind in KiB angegeben).
  • RSS "Real Memory Use" nimmt nur träge zu, wenn wir die Seiten berühren. Zum Beispiel:
    • Beim ersten Druck haben wir extra_memory_committed 0, was bedeutet, dass wir noch keine Seiten berührt haben. RSS ist ein kleines1648 KiB Programm, das für den normalen Programmstart wie Textbereich, Globals usw. zugewiesen wurde.
    • Auf dem zweiten Druck haben wir auf 8388608 KiB == 8GiBSeiten geschrieben. Infolgedessen stieg RSS um genau 8GIB auf8390256 KiB == 8388608 KiB + 1648 KiB
    • RSS nimmt in 8-GB-Schritten weiter zu. Der letzte Druck zeigt ungefähr 24 GiB Speicher, und bevor 32 GiB gedruckt werden konnten, hat der OOM-Killer den Prozess abgebrochen

Siehe auch: /unix/35129/need-explanation-on-resident-set-size-virtual-size

OOM Killer Logs

Unsere dmesgBefehle haben die OOM-Killerprotokolle angezeigt.

Eine genaue Interpretation dieser wurde gefragt bei:

Die allererste Zeile des Protokolls war:

[ 7283.479087] mongod invoked oom-killer: gfp_mask=0x6200ca(GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=0

Interessanterweise sehen wir also, dass der MongoDB-Daemon, der immer in meinem Laptop im Hintergrund ausgeführt wird, den OOM-Killer zuerst ausgelöst hat, vermutlich als das arme Ding versuchte, Speicher zuzuweisen.

Der OOM-Killer tötet jedoch nicht unbedingt denjenigen, der ihn geweckt hat.

Nach dem Aufruf druckt der Kernel eine Tabelle oder Prozesse, einschließlich 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

und weiter vorne sehen wir, dass unser eigenes kleines main.outKind bei der vorherigen Anrufung tatsächlich getötet wurde:

[ 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

In diesem Protokoll wird erwähnt, score 865welche dieser Prozesse vermutlich die höchste (schlechteste) OOM-Killer-Punktzahl hatten, wie unter /unix/153585/how-does-the-oom-killer-decide-which- Prozess, um zuerst zu töten

Interessanterweise ging anscheinend alles so schnell, dass der freigegebene Speicher vor dem oomAbrechnen durch den DeadlineMonitorVorgang wieder geweckt wurde :

[ 7283.481043] DeadlineMonitor invoked oom-killer: gfp_mask=0x6200ca(GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=0

und diesmal hat das einen Chromium-Prozess beendet, der normalerweise der normale Speicher meines Computers ist:

[ 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

Getestet in Ubuntu 19.04, Linux Kernel 5.0.0.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
quelle
8

Ich denke, es wurde bereits viel über RSS vs VSZ gesagt. Aus Administrator- / Programmierer- / Benutzerperspektive mache ich mir beim Entwerfen / Codieren von Anwendungen mehr Sorgen um die RSZ (Resident Memory), und wenn Sie immer mehr Variablen (gehäuft) abrufen, wird dieser Wert in die Höhe schießen. Versuchen Sie es mit einem einfachen Programm, um eine malloc-basierte Speicherplatzzuweisung in einer Schleife zu erstellen, und stellen Sie sicher, dass Sie Daten in diesen malloc-Speicherplatz eingeben. RSS steigt weiter an. In Bezug auf VSZ handelt es sich bei Linux eher um die Zuordnung des virtuellen Speichers als um eine der Kernfunktionen, die aus herkömmlichen Betriebssystemkonzepten abgeleitet wurden. Die VSZ-Verwaltung erfolgt über die Verwaltung des virtuellen Speichers des Kernels. Weitere Informationen zu VSZ finden Sie in der Beschreibung von Robert Love zu mm_struct und vm_struct, die Teil der grundlegenden Datenstruktur task_struct im Kernel sind.

Anugraha Sinha
quelle
Beziehen Sie sich auf das Buch "Linux Kernel Development" von Love?
Benjamin
1

Sie werden nicht verwaltet, sondern gemessen und möglicherweise eingeschränkt (siehe getrlimitSystemaufruf, auch auf getrlimit (2) ).

RSS bedeutet residente Satzgröße (der Teil Ihres virtuellen Adressraums, der sich im RAM befindet).

Sie können den virtuellen Adressraum des Prozesses 1234 mit proc (5) mit cat /proc/1234/mapsund dessen Status (einschließlich Speicherverbrauch) durch abfragencat /proc/1234/status

Basile Starynkevitch
quelle
1
Während dieser Link die Frage beantworten kann, ist es besser, die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz bereitzustellen. Nur-Link-Antworten können ungültig werden, wenn sich die verknüpfte Seite ändert. - Aus der Rezension
Maak
Ich habe einen zweiten Link bereitgestellt. Einer von ihnen bleibt gültig
Basile Starynkevitch