Apa itu RSS dan VSZ dalam manajemen memori Linux

331

Apa RSS dan VSZ dalam manajemen memori Linux? Dalam lingkungan multithreaded bagaimana kedua hal ini dapat dikelola dan dilacak?

tuban
sumber
kemungkinan duplikat dari Understanding the Linux oom-killer's log
msangel

Jawaban:

499

RSS adalah Resident Set Size dan digunakan untuk menunjukkan berapa banyak memori yang dialokasikan untuk proses itu dan dalam RAM. Itu tidak termasuk memori yang ditukar. Itu tidak termasuk memori dari perpustakaan bersama selama halaman dari perpustakaan itu benar-benar dalam memori. Itu tidak termasuk semua memori tumpukan dan tumpukan.

VSZ adalah Ukuran Memori Virtual. Ini mencakup semua memori yang dapat diakses oleh proses, termasuk memori yang ditukar, memori yang dialokasikan, tetapi tidak digunakan, dan memori yang berasal dari perpustakaan bersama.

Jadi jika proses A memiliki biner 500K dan terhubung ke 2500K perpustakaan bersama, memiliki 200K alokasi tumpukan / tumpukan yang 100K sebenarnya ada dalam memori (sisanya ditukar atau tidak digunakan), dan ia hanya memuat 1000K perpustakaan bersama dan 400 ribu binernya sendiri:

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

Karena sebagian dari memori dibagi, banyak proses dapat menggunakannya, jadi jika Anda menambahkan semua nilai RSS Anda dapat dengan mudah berakhir dengan lebih banyak ruang daripada yang dimiliki sistem Anda.

Memori yang dialokasikan juga mungkin tidak di RSS sampai benar-benar digunakan oleh program. Jadi jika program Anda mengalokasikan banyak memori di muka, kemudian menggunakannya dari waktu ke waktu, Anda bisa melihat RSS naik dan VSZ tetap sama.

Ada juga PSS (ukuran set proporsional). Ini adalah ukuran yang lebih baru yang melacak memori bersama sebagai proporsi yang digunakan oleh proses saat ini. Jadi jika ada dua proses menggunakan pustaka bersama yang sama dari sebelumnya:

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

Semua utas berbagi ruang alamat yang sama, sehingga RSS, VSZ dan PSS untuk setiap utas identik dengan semua utas lainnya dalam proses. Gunakan ps atau atas untuk melihat informasi ini di linux / unix.

Ada cara lebih dari ini, untuk mempelajari lebih lanjut, periksa referensi berikut:

Lihat juga:

jmh
sumber
17
Saya percaya RSS tidak termasuk memori dari perpustakaan dinamis terhubung. Jika ada 3 proses menggunakan libxml2.so, perpustakaan bersama akan dihitung di setiap RSS mereka, sehingga jumlah RSS mereka akan lebih dari memori sebenarnya yang digunakan.
nfm
1
Itu betul. Saya telah memperbaiki jawaban saya, terima kasih atas perhatiannya.
jmh
Saya di ubuntu 16.04, dan ada proses java memiliki 1.2G RES dan 4.5G VIRT menunjukkan dari topperintah. Sistem ini tidak memiliki swap apa pun, swapon --showtidak menghasilkan apa-apa. Bagaimana Anda menjelaskan ini? Jika vsz adalah swap + shared library, dalam hal ini, shared library lebih dari 3.3G? Apa itu mungkin? Benar-benar bingung ...
Aaron Wang
Saya tidak begitu yakin. Lihatlah jawaban ini pada penggunaan memori virtual Java: stackoverflow.com/a/561450/622115 . Versi singkat: VSZ dapat mencakup ruang tumpukan yang dialokasikan dan tidak digunakan serta file yang dipetakan memori.
jmh
Bagus. Cukup tambahkan sesuatu. jika Anda malloc (100KB), maka sebenarnya hanya menggunakan 1KB. Rss adalah 1K dan vsz adalah 100K, bahkan jika tidak ada swap di sini.
keniee van
53

RSS adalah Resident Set Size (memori resident fisik - ini saat ini menempati ruang dalam memori fisik mesin), dan VSZ adalah Virtual Memory Size (ruang alamat dialokasikan - ini memiliki alamat yang dialokasikan dalam peta memori proses, tetapi belum tentu ada memori yang sebenarnya di balik itu semua sekarang).

Perhatikan bahwa pada hari-hari ini mesin virtual biasa, memori fisik dari sudut pandang mesin mungkin tidak benar-benar memori fisik yang sebenarnya.

kaf
sumber
Pikiran memberikan lebih banyak info daripada singkatan untuk apa?
Pithikos
10

Contoh runnable minimal

Agar ini masuk akal, Anda harus memahami dasar-dasar paging: Bagaimana cara kerja paging x86? dan khususnya bahwa OS dapat mengalokasikan memori virtual melalui tabel halaman / pembukuan memori internalnya (memori virtual VSZ) sebelum benar-benar memiliki penyimpanan dukungan pada RAM atau disk (memori residen RSS).

Sekarang untuk mengamati ini dalam tindakan, mari kita buat program yang:

  • mengalokasikan lebih banyak RAM daripada memori fisik kita dengan mmap
  • menulis satu byte pada setiap halaman untuk memastikan bahwa masing-masing halaman berjalan dari memori hanya virtual (VSZ) ke memori yang sebenarnya digunakan (RSS)
  • memeriksa penggunaan memori proses dengan salah satu metode yang disebutkan di: Penggunaan memori proses saat ini di 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 hulu .

Kompilasi dan jalankan:

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

dimana:

  • 0x1000000000 == 64GiB: 2x RAM fisik komputer saya sebesar 32GiB
  • 0x200000000 == 8GiB: cetak memori setiap 8GiB, jadi kita harus mendapatkan 4 cetakan sebelum crash sekitar 32GiB
  • echo 1 | sudo tee /proc/sys/vm/overcommit_memory: diperlukan untuk Linux agar kami dapat membuat panggilan mmap lebih besar dari RAM fisik: memori maksimum yang dapat dialokasikan malloc

Output program:

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 keluar:

137

yang dengan aturan nomor sinyal 128+ berarti kami mendapat nomor sinyal 9, yang man 7 signalmengatakan adalah SIGKILL , yang dikirim oleh Linux out-of-memory killer .

Interpretasi keluaran:

  • Memori virtual VSZ tetap konstan pada printf '0x%X\n' 0x40009A4 KiB ~= 64GiB( psnilai-nilai dalam KiB) setelah mmap.
  • RSS "penggunaan memori nyata" hanya meningkat malas saat kita menyentuh halaman. Sebagai contoh:
    • pada cetakan pertama, kita miliki extra_memory_committed 0, yang berarti kita belum menyentuh halaman mana pun. RSS adalah kecil 1648 KiByang telah dialokasikan untuk startup program normal seperti area teks, global, dll.
    • pada cetakan kedua, kami telah menulis hingga 8388608 KiB == 8GiBsenilai halaman. Akibatnya, RSS meningkat hingga 8GIB menjadi8390256 KiB == 8388608 KiB + 1648 KiB
    • RSS terus meningkat dengan peningkatan 8GiB. Hasil cetak terakhir menunjukkan memori sekitar 24 GiB, dan sebelum 32 GiB dapat dicetak, pembunuh OOM tersebut mematikan prosesnya

Lihat juga: /unix/35129/need-explanation-on-resident-set-size-virtual-size

Log pembunuh OOM

dmesgPerintah kami telah menunjukkan log pembunuh OOM.

Penafsiran yang tepat dari mereka telah ditanyakan di:

Baris pertama dari log adalah:

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

Jadi kita melihat bahwa yang menarik adalah daemon MongoDB yang selalu berjalan di laptop saya di latar belakang yang pertama kali memicu pembunuh OOM, mungkin ketika hal yang buruk itu mencoba mengalokasikan beberapa memori.

Namun, pembunuh OOM tidak harus membunuh orang yang membangunkannya.

Setelah doa, kernel mencetak tabel atau proses termasuk 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

dan lebih jauh ke depan kita melihat bahwa anak kita sendiri main.outbenar - benar terbunuh pada doa sebelumnya:

[ 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

Log ini menyebutkan score 865proses yang memiliki, mungkin skor pembunuh OOM tertinggi (terburuk) seperti disebutkan di: /unix/153585/how-do -the-oom-killer-decide- which- proses-untuk-membunuh-pertama

Yang juga menarik, segala sesuatu tampaknya terjadi begitu cepat sehingga sebelum ingatan yang dibebaskan dicatat, oomdibangunkan kembali oleh DeadlineMonitorproses:

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

dan kali ini yang menewaskan beberapa proses Chromium, yang biasanya komputer saya memori normal babi:

[ 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

Diuji di Ubuntu 19.04, kernel Linux 5.0.0.

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

Saya pikir banyak yang telah dikatakan, tentang RSS vs VSZ. Dari perspektif administrator / programmer / pengguna, ketika saya mendesain / kode aplikasi saya lebih peduli tentang RSZ, (memori penduduk), dan ketika Anda terus menarik lebih banyak variabel (heaped), Anda akan melihat nilai ini naik. Coba program sederhana untuk membangun alokasi ruang berbasis malloc di loop, dan pastikan Anda mengisi data di ruang malloc'd itu. RSS terus bergerak. Sejauh menyangkut VSZ, lebih dari pemetaan memori virtual yang dilakukan linux, dan salah satu fitur intinya berasal dari konsep sistem operasi konvensional. Manajemen VSZ dilakukan oleh manajemen memori virtual kernel, untuk info lebih lanjut tentang VSZ, lihat deskripsi Robert Love pada mm_struct dan vm_struct, yang merupakan bagian dari struktur data task_struct dasar dalam kernel.

Anugraha Sinha
sumber
Apakah Anda merujuk pada buku "Pengembangan Kernel Linux" oleh Love?
benjimin
1

Mereka tidak dikelola, tetapi diukur dan mungkin terbatas (lihat getrlimitsystem call, juga pada getrlimit (2) ).

RSS berarti ukuran yang ditetapkan penduduk (bagian dari ruang alamat virtual Anda yang tersimpan dalam RAM).

Anda dapat meminta ruang alamat virtual proses 1234 menggunakan proc (5) dengan cat /proc/1234/mapsdan statusnya (termasuk konsumsi memori) melaluicat /proc/1234/status

Basile Starynkevitch
sumber
1
Meskipun tautan ini dapat menjawab pertanyaan, lebih baik untuk memasukkan bagian-bagian penting dari jawaban di sini dan memberikan tautan untuk referensi. Jawaban hanya tautan dapat menjadi tidak valid jika halaman tertaut berubah. - Dari Ulasan
Maak
Saya memberikan tautan kedua. Salah satunya akan tetap berlaku
Basile Starynkevitch