Antworten:
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:
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.
top
Befehl angezeigt wird . Dieses System hat keinen Swap, swapon --show
gibt 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 ...
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.
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:
mmap
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;
}
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:
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 kannProgrammausgabe:
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 signal
sagt , ist SIGKILL , die von der Linux gesendet wird , out-of-Memory - Killer .
Ausgangsinterpretation:
printf '0x%X\n' 0x40009A4 KiB ~= 64GiB
( ps
Werte sind in KiB angegeben).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.8388608 KiB == 8GiB
Seiten geschrieben. Infolgedessen stieg RSS um genau 8GIB auf8390256 KiB == 8388608 KiB + 1648 KiB
Siehe auch: /unix/35129/need-explanation-on-resident-set-size-virtual-size
OOM Killer Logs
Unsere dmesg
Befehle 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.out
Kind 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 865
welche 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 oom
Abrechnen durch den DeadlineMonitor
Vorgang 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.
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.
Sie werden nicht verwaltet, sondern gemessen und möglicherweise eingeschränkt (siehe getrlimit
Systemaufruf, 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/maps
und dessen Status (einschließlich Speicherverbrauch) durch abfragencat /proc/1234/status