Odpowiedzi:
RSS to Resident Set Size i służy do pokazania, ile pamięci jest przydzielone do tego procesu i czy znajduje się w pamięci RAM. Nie obejmuje wymienionej pamięci. Obejmuje pamięć z bibliotek współdzielonych, o ile strony z tych bibliotek znajdują się w pamięci. Obejmuje całą pamięć stosu i sterty.
VSZ to rozmiar pamięci wirtualnej. Obejmuje całą pamięć, do której proces może uzyskać dostęp, w tym pamięć wymienną, pamięć przydzieloną, ale nieużywaną oraz pamięć pochodzącą z bibliotek współdzielonych.
Więc jeśli proces A ma 500 KB pliku binarnego i jest połączony z 2500 KB bibliotek współużytkowanych, ma 200 000 przydziałów stosu / sterty, z których 100 000 faktycznie znajduje się w pamięci (reszta jest zamieniona lub nieużywana) i faktycznie załadował tylko 1000 KB bibliotek współdzielonych i 400 KB własnego pliku binarnego następnie:
RSS: 400K + 1000K + 100K = 1500K
VSZ: 500K + 2500K + 200K = 3200K
Ponieważ część pamięci jest współdzielona, wiele procesów może z niej korzystać, więc jeśli dodasz wszystkie wartości RSS, możesz z łatwością uzyskać więcej miejsca niż system.
Przydzielona pamięć może również nie znajdować się w RSS, dopóki nie zostanie faktycznie wykorzystana przez program. Więc jeśli twój program przydzielił sporo pamięci z góry, a następnie zużywa ją z czasem, możesz zobaczyć, jak RSS się podnosi, a VSZ pozostaje taki sam.
Istnieje również PSS (proporcjonalny rozmiar zestawu). Jest to nowsza miara, która śledzi pamięć współdzieloną jako część wykorzystywaną przez bieżący proces. Więc jeśli dwa procesy korzystały z tej samej biblioteki współużytkowanej wcześniej:
PSS: 400K + (1000K/2) + 100K = 400K + 500K + 100K = 1000K
Wszystkie wątki mają tę samą przestrzeń adresową, więc RSS, VSZ i PSS dla każdego wątku są identyczne z wszystkimi innymi wątkami w tym procesie. Użyj ps lub top, aby wyświetlić te informacje w systemie Linux / UNIX.
Jest o wiele więcej niż to, aby dowiedzieć się więcej, sprawdź następujące referencje:
Zobacz także:
libxml2.so, biblioteka współdzielona będzie zliczana w każdym z ich kanałów RSS, więc suma ich kanałów RSS będzie większa niż faktyczna używana pamięć.
toppolecenia. Ten system nie ma żadnej wymiany, swapon --shownic nie zwraca. Jak to wytłumaczysz? Jeśli vsz to swap + biblioteki współdzielone, w takim przypadku biblioteki współdzielone są większe niż 3.3G? Czy to możliwe? Po prostu bardzo zdezorientowany ...
RSS to Resident Set Size (fizycznie rezydentna pamięć - obecnie zajmuje miejsce w pamięci fizycznej maszyny), a VSZ to Virtual Memory Size (przydzielona przestrzeń adresowa - ma adresy przydzielone na mapie pamięci procesu, ale niekoniecznie rzeczywista pamięć za tym wszystkim teraz).
Należy pamiętać, że w dzisiejszych czasach zwykłych maszyn wirtualnych pamięć fizyczna z punktu widzenia maszyny może nie być tak naprawdę rzeczywistą pamięcią fizyczną.
Minimalny możliwy do uruchomienia przykład
Aby to miało sens, musisz zrozumieć podstawy stronicowania: Jak działa stronicowanie x86? aw szczególności, że system operacyjny może przydzielić pamięć wirtualną za pomocą tablic stron / przechowywania wewnętrznej pamięci (pamięć wirtualna VSZ), zanim faktycznie będzie miała pamięć zapasową na RAM lub dysku (pamięć rezydentna RSS).
Teraz, aby to zaobserwować w akcji, stwórzmy program, który:
mmapmain.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;
}
Skompiluj i uruchom:
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
gdzie:
echo 1 | sudo tee /proc/sys/vm/overcommit_memory: wymagany dla Linuksa, abyśmy mogli wykonać połączenie mmap większe niż fizyczna pamięć RAM: maksymalna pamięć, którą malloc może przydzielićWyjście programu:
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
Status wyjścia:
137
co według reguły liczby 128 + oznacza, że otrzymaliśmy numer sygnału 9, który man 7 signalmówi , że to SIGKILL , który jest wysyłany przez zabójcę braku pamięci w systemie Linux .
Interpretacja wyjściowa:
printf '0x%X\n' 0x40009A4 KiB ~= 64GiB( pswartości w KiB) po mmap.extra_memory_committed 0, co oznacza, że jeszcze nie dotknęliśmy żadnych stron. RSS to mały plik 1648 KiBprzeznaczony do normalnego uruchamiania programu, takiego jak obszar tekstowy, globały itp.8388608 KiB == 8GiBwartości stron. W rezultacie RSS wzrosła dokładnie o 8 GIB do8390256 KiB == 8388608 KiB + 1648 KiBZobacz także: /unix/35129/need-explanation-on-resident-set-size-virtual-size
Dzienniki zabójców OOM
Nasze dmesgpolecenia pokazały dzienniki zabójców OOM.
Dokładna ich interpretacja została zapytana na:
Pierwszą linią dziennika było:
[ 7283.479087] mongod invoked oom-killer: gfp_mask=0x6200ca(GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=0
Widzimy więc, co ciekawe, to demon MongoDB, który zawsze działa w moim laptopie w tle, który jako pierwszy wyzwalał zabójcę OOM, prawdopodobnie gdy biedak próbował przydzielić trochę pamięci.
Jednak zabójca OOM niekoniecznie zabija tego, który go obudził.
Po wywołaniu jądro drukuje tabelę lub procesy, w tym 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
a dalej widzimy, że nasze własne małe main.outtak naprawdę zginęło podczas poprzedniego wywołania:
[ 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
Ten dziennik wspomina, score 865jaki proces ten miał, prawdopodobnie najwyższy (najgorszy) wynik zabójcy OOM, jak wspomniano na stronie : /unix/153585/how-does-the-oom-killer-decide-which- Najpierw proces do zabicia
Co ciekawe, wszystko najwyraźniej stało się tak szybko, że zanim uwolniona pamięć została rozliczona, proces oomzostał ponownie obudzony DeadlineMonitor:
[ 7283.481043] DeadlineMonitor invoked oom-killer: gfp_mask=0x6200ca(GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=0
i tym razem zabił proces Chromium, który zwykle jest normalnym zapisem pamięci mojego komputera:
[ 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
Testowany w Ubuntu 19.04, jądro Linuksa 5.0.0.
Myślę, że wiele już powiedziano o RSS vs VSZ. Z punktu widzenia administratora / programisty / użytkownika, kiedy projektuję / koduję aplikacje, bardziej martwię się o RSZ (pamięć rezydentna), ponieważ kiedy będziesz wyciągał coraz więcej zmiennych (stos), zobaczysz, że ta wartość rośnie. Wypróbuj prosty program do tworzenia pętli przydziału miejsca opartego na malloc i upewnij się, że wypełniłeś dane w tym miejscu malloc. RSS przesuwa się w górę. Jeśli chodzi o VSZ, bardziej chodzi o mapowanie pamięci wirtualnej niż Linux, a jedną z jego podstawowych funkcji są wywodzące się z konwencjonalnych koncepcji systemów operacyjnych. Zarządzanie VSZ odbywa się za pomocą wirtualnego zarządzania pamięcią jądra, aby uzyskać więcej informacji na temat VSZ, zobacz opis Roberta Love'a na mm_struct i vm_struct, które są częścią podstawowej struktury danych task_struct w jądrze.
Nie są zarządzane, ale mierzone i prawdopodobnie ograniczone (patrz getrlimitwywołanie systemowe, także na getrlimit (2) ).
RSS oznacza rezydentny rozmiar zestawu (część wirtualnej przestrzeni adresowej siedzącej w pamięci RAM).
Można kwerendy wirtualną przestrzeń adresową procesu 1234 użyciem proc (5) z cat /proc/1234/mapsoraz jego status (w tym zużycie pamięci) thrucat /proc/1234/status