Що таке RSS та VSZ в управлінні пам’яттю Linux


Відповіді:


499

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.

Існує набагато більше, ніж це, щоб дізнатися більше перевірити наступні посилання:

Також дивіться:


17
Я вважаю , що RSS дійсно включає в себе пам'ять з динамічно підключаються бібліотек. Якщо використовуються 3 процеси libxml2.so, спільна бібліотека буде рахуватися у кожному їхньому RSS, тому сума їх RSS буде більшою, ніж фактично використана пам'ять.
nfm

1
Це правильно. Я виправив свою відповідь, дякую за голову вгору.
jmh

Я перебуваю на ubuntu 16.04, і там у java-процесі є 1.2G RES та 4.5G VIRT, показані з topкоманди. Ця система не має жодного свопу, swapon --showнічого не повертає. Як ви це пояснюєте? Якщо vsz - це swap + спільні бібліотеки, то в цьому випадку спільні бібліотеки перевищують 3,3G? Це можливо? Просто справді розгублено ...
Аарон Ван

Я не дуже впевнений. Подивіться на цю відповідь щодо використання віртуальної пам'яті Java: stackoverflow.com/a/561450/622115 . Коротка версія: VSZ може містити кучу простору, яка виділяється і не використовується, а також файли, відображені в пам'яті.
jmh

Чудово. Просто додайте щось. якщо ви malloc (100KB), тоді фактично використовуйте лише 1KB. Rss - 1K, а vsz - 100K, навіть якщо тут немає свопів.
keniee van

53

RSS - це розмір встановленого резидента (фізична пам'ять-резидент - це зараз займає місце у фізичній пам'яті машини), а VSZ - розмір віртуальної пам’яті (виділений адресний простір - це адреси, виділені в карті пам'яті процесу, але не обов'язково є фактична пам'ять за цим все зараз).

Зауважте, що в ці дні звичайних віртуальних машин фізична пам'ять з точки зору машини може насправді не бути фактичною фізичною пам'яттю.


Розум надає більше інформації, ніж те, що означає абревіатура?
Пітікос

10

Приклад мінімальної експлуатації

Щоб це мало сенс, ви повинні зрозуміти основи підкачки: Як працює підказка x86? і, зокрема, що ОС може виділяти віртуальну пам'ять за допомогою таблиць сторінок / її внутрішнього зберігання книги пам'яті (VSZ віртуальної пам’яті) до того, як вона фактично має резервну пам’ять на оперативній пам’яті чи диску (RSS-пам'ять).

Тепер, щоб спостерігати за цим у дії, давайте створимо програму, яка:

  • виділяє більше оперативної пам'яті, ніж наша фізична пам'ять mmap
  • пише по одному байту на кожну сторінку, щоб переконатися, що кожна з цих сторінок переходить від віртуальної пам'яті (VSZ) до фактично використовуваної пам'яті (RSS)
  • перевіряє використання пам'яті процесу одним із методів, згаданих у: Використання пам'яті поточного процесу в 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 вище за течією .

Складіть і запустіть:

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

де:

  • 0x1000000000 == 64GiB: 2x фізична оперативна пам'ять мого комп'ютера 32GiB
  • 0x200000000 == 8GiB: друкуйте пам’ять кожні 8GiB, тому ми повинні отримати 4 відбитки до краху приблизно на 32GiB
  • 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 .

Інтерпретація результатів:

  • Віртуальна пам'ять VSZ залишається постійною на рівні printf '0x%X\n' 0x40009A4 KiB ~= 64GiB( psзначення є в KiB) після mmap.
  • RSS "реальне використання пам'яті" ліниво збільшується лише тоді, коли ми торкаємось сторінок. Наприклад:
    • Перший друк у нас є extra_memory_committed 0, це означає, що ми ще не торкнулися жодної сторінки. RSS - це невеликий 1648 KiBрозмір, який виділяється для нормального запуску програми, наприклад, текстова область, глобальні тощо.
    • у другому друку ми написали 8388608 KiB == 8GiBвартістю сторінок. Як результат, RSS збільшився точно на 8GIB до8390256 KiB == 8388608 KiB + 1648 KiB
    • RSS продовжує збільшуватися з кроком 8 Гбіт. Останній друк показує близько 24 ГБ пам’яті, і до того, як можна було надрукувати 32 Гб, вбивця ООМ вбив процес

Дивіться також: /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.


8

Я думаю, що вже багато сказано про RSS vs VSZ. З точки зору адміністратора / програміста / користувача, коли я розробляю / кодую програми, мене більше турбує RSZ, (Пам'ять резидента), як і коли ви продовжуватимете тягнути все більше і більше змінних (нагромаджених), ви побачите, що це значення збільшується. Спробуйте просту програму для побудови розподілу простору на основі malloc у циклі та переконайтеся, що ви заповнюєте дані у цьому просторі malloc'd. RSS продовжує рухатися вгору. Що стосується VSZ, то це більше віртуальне відображення пам’яті, що робить Linux, і одна з його основних функцій, що випливає із звичайних концепцій операційної системи. Управління VSZ здійснюється за допомогою управління віртуальною пам’яттю ядра, для отримання додаткової інформації про VSZ див. Опис Роберта Лава на mm_struct та vm_struct, які є частиною основної структури даних task_struct в ядрі.


Ви маєте на увазі книгу "Linux Kernel Development" від Love?
benjimin

1

Вони не управляються, але вимірюються і, можливо, обмежуються (див. getrlimitСистемний виклик, також на getrlimit (2) ).

RSS означає розмір встановленого резидента (частина вашого віртуального адресного простору, що сидить в оперативній пам'яті).

Ви можете запитувати віртуальний адресний простір процесу 1234 за допомогою proc (5) з cat /proc/1234/mapsта його статусом (включаючи споживання пам'яті) черезcat /proc/1234/status


1
Хоча це посилання може відповісти на питання, краще включити сюди суттєві частини відповіді та надати посилання для довідки. Відповіді лише на посилання можуть стати недійсними, якщо пов’язана сторінка зміниться. - З огляду
Maak

Я надав друге посилання. Один із них залишиться дійсним
Базиле Старинкевич
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.