Відповіді:
RSS - це розмір постійного набору і використовується для показу кількості пам'яті, що виділяється на цей процес і в оперативній пам'яті. Він не включає пам’ять, яку заміняють. Він включає пам’ять із спільних бібліотек до тих пір, поки сторінки з цих бібліотек насправді є в пам'яті. Він включає в себе всю стек і купу пам'яті.
VSZ - це розмір віртуальної пам'яті. Вона включає всю пам’ять, до якої процес може отримати доступ, включаючи пам'ять, що перебуває у вільному обміні, пам'ять, яка виділяється, але не використовується, і пам'ять, що знаходиться в спільних бібліотеках.
Отже, якщо процес A має двійкову 500K і пов'язаний з 2500K спільних бібліотек, має 200K виділень стека / купи, з яких 100K фактично є в пам'яті (решта поміняється або не використовується), і він фактично завантажив лише 1000K спільних бібліотек і 400K власних двійкових даних:
RSS: 400K + 1000K + 100K = 1500K
VSZ: 500K + 2500K + 200K = 3200K
Оскільки частина пам'яті поділяється, багато процесів можуть використовувати її, тому якщо ви додасте всі значення RSS, ви можете легко отримати більше місця, ніж у вашій системі.
Пам'ять, яка виділяється, також може не знаходитися в RSS, поки вона фактично не використовується програмою. Тож якщо ваша програма виділила перед собою купу пам’яті, а потім використовує її з часом, ви зможете побачити, як RSS піднімається, а VSZ залишається тим самим.
Також є PSS (пропорційний розмір заданих). Це новіший показник, який відстежує загальну пам'ять як пропорцію, що використовується в поточному процесі. Тож якщо раніше було два процеси, що використовують одну і ту ж спільну бібліотеку:
PSS: 400K + (1000K/2) + 100K = 400K + 500K + 100K = 1000K
Усі нитки мають однаковий адресний простір, тому RSS, VSZ та PSS для кожного потоку ідентичні всім іншим потокам у процесі. Використовуйте ps або top для перегляду цієї інформації в linux / unix.
Існує набагато більше, ніж це, щоб дізнатися більше перевірити наступні посилання:
Також дивіться:
libxml2.so
, спільна бібліотека буде рахуватися у кожному їхньому RSS, тому сума їх RSS буде більшою, ніж фактично використана пам'ять.
top
команди. Ця система не має жодного свопу, swapon --show
нічого не повертає. Як ви це пояснюєте? Якщо vsz - це swap + спільні бібліотеки, то в цьому випадку спільні бібліотеки перевищують 3,3G? Це можливо? Просто справді розгублено ...
RSS - це розмір встановленого резидента (фізична пам'ять-резидент - це зараз займає місце у фізичній пам'яті машини), а VSZ - розмір віртуальної пам’яті (виділений адресний простір - це адреси, виділені в карті пам'яті процесу, але не обов'язково є фактична пам'ять за цим все зараз).
Зауважте, що в ці дні звичайних віртуальних машин фізична пам'ять з точки зору машини може насправді не бути фактичною фізичною пам'яттю.
Приклад мінімальної експлуатації
Щоб це мало сенс, ви повинні зрозуміти основи підкачки: Як працює підказка x86? і, зокрема, що ОС може виділяти віртуальну пам'ять за допомогою таблиць сторінок / її внутрішнього зберігання книги пам'яті (VSZ віртуальної пам’яті) до того, як вона фактично має резервну пам’ять на оперативній пам’яті чи диску (RSS-пам'ять).
Тепер, щоб спостерігати за цим у дії, давайте створимо програму, яка:
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;
}
Складіть і запустіть:
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
де:
echo 1 | sudo tee /proc/sys/vm/overcommit_memory
: потрібно для Linux, щоб ми могли зробити mmap-виклик більше, ніж фізична оперативна пам'ять: максимальна пам'ять, яку malloc може виділитиВихід програми:
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
Стан виходу:
137
що за правилом 128 + сигнал сигналу означає, що ми отримали номер сигналу 9
, який man 7 signal
говорить про SIGKILL , який надсилається вбивцею поза пам'яті Linux .
Інтерпретація результатів:
printf '0x%X\n' 0x40009A4 KiB ~= 64GiB
( ps
значення є в KiB) після mmap.extra_memory_committed 0
, це означає, що ми ще не торкнулися жодної сторінки. RSS - це невеликий 1648 KiB
розмір, який виділяється для нормального запуску програми, наприклад, текстова область, глобальні тощо.8388608 KiB == 8GiB
вартістю сторінок. Як результат, RSS збільшився точно на 8GIB до8390256 KiB == 8388608 KiB + 1648 KiB
Дивіться також: /unix/35129/need-explanation-on-resident-set-size-virtual-size
Журнали вбивць OOM
Наші dmesg
команди показали журнали вбивць OOM.
Точне тлумачення цих запитань було запропоновано на:
Першим рядком журналу був:
[ 7283.479087] mongod invoked oom-killer: gfp_mask=0x6200ca(GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=0
Таким чином, ми бачимо, що цікаво, що саме демон MongoDB завжди працює в моєму ноутбуці на тлі, який вперше викликав вбивцю OOM, імовірно, коли бідна людина намагалася виділити трохи пам'яті.
Однак вбивця ООМ не обов'язково вбиває того, хто його пробудив.
Після виклику ядро друкує таблицю або процеси, включаючи 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
і далі ми бачимо, що наш власний маленький main.out
насправді був убитий під час попереднього виклику:
[ 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
Цей журнал зазначає, score 865
що цей процес мав, мабуть, найвищий (найгірший) бал вбивць OOM, як згадується на веб-сторінці : /unix/153585/how-does-the-oom-killer-decide-which- процес-вбити-першим
Цікаво також, що все, мабуть, сталося так швидко, що перед тим, як звільнити пам'ять, процес oom
знову пробудився DeadlineMonitor
:
[ 7283.481043] DeadlineMonitor invoked oom-killer: gfp_mask=0x6200ca(GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=0
і цього разу вбив деякий процес Chromium, який, як правило, у моїх комп’ютерах - звичайна свиня пам'яті:
[ 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
Тестовано в Ubuntu 19.04, Linux kernel 5.0.0.
Я думаю, що вже багато сказано про RSS vs VSZ. З точки зору адміністратора / програміста / користувача, коли я розробляю / кодую програми, мене більше турбує RSZ, (Пам'ять резидента), як і коли ви продовжуватимете тягнути все більше і більше змінних (нагромаджених), ви побачите, що це значення збільшується. Спробуйте просту програму для побудови розподілу простору на основі malloc у циклі та переконайтеся, що ви заповнюєте дані у цьому просторі malloc'd. RSS продовжує рухатися вгору. Що стосується VSZ, то це більше віртуальне відображення пам’яті, що робить Linux, і одна з його основних функцій, що випливає із звичайних концепцій операційної системи. Управління VSZ здійснюється за допомогою управління віртуальною пам’яттю ядра, для отримання додаткової інформації про VSZ див. Опис Роберта Лава на mm_struct та vm_struct, які є частиною основної структури даних task_struct в ядрі.
Вони не управляються, але вимірюються і, можливо, обмежуються (див. getrlimit
Системний виклик, також на getrlimit (2) ).
RSS означає розмір встановленого резидента (частина вашого віртуального адресного простору, що сидить в оперативній пам'яті).
Ви можете запитувати віртуальний адресний простір процесу 1234 за допомогою proc (5) з cat /proc/1234/maps
та його статусом (включаючи споживання пам'яті) черезcat /proc/1234/status