लिनक्स मेमोरी मैनेजमेंट में RSS और VSZ क्या है


331

लिनक्स मेमोरी मैनेजमेंट में RSS और VSZ क्या हैं? एक बहुआयामी वातावरण में इन दोनों को कैसे प्रबंधित और ट्रैक किया जा सकता है?


जवाबों:


499

RSS निवासी सेट आकार है और यह दिखाने के लिए उपयोग किया जाता है कि उस प्रक्रिया में कितनी मेमोरी आवंटित की गई है और RAM में है। इसमें वह मेमोरी शामिल नहीं है जिसे स्वैप किया गया है। इसमें साझा पुस्तकालयों से मेमोरी शामिल है, जब तक कि उन पुस्तकालयों के पृष्ठ वास्तव में स्मृति में हैं। इसमें सभी स्टैक और हीप मेमोरी शामिल हैं।

VSZ वर्चुअल मेमोरी साइज है। इसमें सभी मेमोरी शामिल हैं जो इस प्रक्रिया तक पहुंच सकते हैं, जिसमें स्वैप की गई मेमोरी भी शामिल है, मेमोरी जो आवंटित की गई है, लेकिन इसका उपयोग नहीं किया गया है, और मेमोरी जो कि साझा लाइब्रेरी से है।

इसलिए यदि प्रक्रिया A में 500K बाइनरी है और साझा पुस्तकालयों के 2500K से जुड़ा हुआ है, तो 200K का स्टैक / हीप आवंटन है, जिसमें से 100K वास्तव में मेमोरी में है (बाकी की अदला-बदली या अप्रयुक्त है), और यह केवल साझा पुस्तकालयों के 1000K को लोड करता है और 400K अपने स्वयं के बाइनरी तब:

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

चूंकि मेमोरी का हिस्सा साझा किया जाता है, कई प्रक्रियाएं इसका उपयोग कर सकती हैं, इसलिए यदि आप आरएसएस के सभी मूल्यों को जोड़ते हैं तो आप आसानी से अपने सिस्टम की तुलना में अधिक स्थान के साथ समाप्त हो सकते हैं।

जो मेमोरी आवंटित की जाती है वह आरएसएस में भी नहीं हो सकती है जब तक कि वह वास्तव में प्रोग्राम द्वारा उपयोग नहीं की जाती है। इसलिए यदि आपके कार्यक्रम को सामने स्मृति का एक गुच्छा आवंटित किया गया है, तो समय के साथ इसका उपयोग करता है, तो आप देख सकते हैं कि आरएसएस ऊपर जा रहा है और वीएसजेड वही रह रहा है।

PSS (आनुपातिक सेट आकार) भी है। यह एक नया उपाय है जो साझा मेमोरी को वर्तमान प्रक्रिया द्वारा उपयोग किए गए अनुपात के रूप में ट्रैक करता है। तो अगर पहले से एक ही साझा पुस्तकालय का उपयोग करते हुए दो प्रक्रियाएं थीं:

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

थ्रेड्स सभी समान पता स्थान साझा करते हैं, इसलिए प्रत्येक थ्रेड के लिए RSS, VSZ और PSS प्रक्रिया में अन्य सभी थ्रेड्स के समान है। Linux / unix में इस जानकारी को देखने के लिए ps या top का उपयोग करें।

निम्नलिखित संदर्भों को और अधिक जानने के लिए, इसके अलावा और भी कई तरीके हैं:

और देखें:


17
मेरा मानना ​​है कि आरएसएस गतिशील रूप से जुड़े पुस्तकालयों से स्मृति को शामिल करता है । यदि 3 प्रक्रियाओं का उपयोग किया जाता है libxml2.so, तो साझा पुस्तकालय को उनके प्रत्येक आरएसएस में गिना जाएगा, इसलिए उनके आरएसएस का योग उपयोग की जाने वाली वास्तविक मेमोरी से अधिक होगा।
nfm

1
वह सही है। मैंने अपना जवाब तय कर लिया है, सिर ऊपर करने के लिए धन्यवाद।
jmh

मैं ubuntu 16.04 पर हूं, और एक जावा प्रक्रिया है जिसमें 1.2G RES और 4.5G VIRT topकमांड से दिखा रहा है । इस प्रणाली में कोई स्वैप नहीं है, swapon --showकुछ भी नहीं देता है। यह आपके द्वारा कैसे समझाया जाता है? यदि vsz स्वैप + साझा लाइब्रेरी है, तो इस मामले में, साझा लाइब्रेरी 3.3G से अधिक है? क्या यह संभव है? बस वास्तव में भ्रमित ...
हारून वांग

मैं बहुत पक्का नहीं हूँ। जावा आभासी स्मृति के उपयोग पर इस जवाब पर एक नज़र डालें: stackoverflow.com/a/561450/622115 । लघु संस्करण: वीएसजेड में ढेर स्थान शामिल हो सकता है जो आवंटित किया गया है और साथ ही साथ मेमोरी मैप की गई फ़ाइलों का उपयोग नहीं किया गया है।
jmh

महान। बस कुछ जोड़ें। यदि आप मॉलोक (100KB) करते हैं, तो वास्तव में केवल 1KB का उपयोग करें। Rss 1K है और vsz 100K है, भले ही यहाँ कोई स्वैप न हो।
केनी वैन

53

RSS निवासी सेट आकार है (भौतिक रूप से निवासी मेमोरी - यह वर्तमान में मशीन की भौतिक मेमोरी में स्थान घेर रहा है), और VSZ वर्चुअल मेमोरी साइज (पता स्थान आवंटित किया गया है) - इसमें प्रक्रिया के मेमोरी मैप में आवंटित पते हैं, लेकिन जरूरी नहीं है इसके पीछे वास्तविक स्मृति अभी)।

ध्यान दें कि आम आभासी मशीनों के इन दिनों में, मशीन के दृष्टिकोण से भौतिक मेमोरी वास्तव में वास्तविक भौतिक मेमोरी नहीं हो सकती है।


संक्षिप्त नाम प्रदान करने की तुलना में अधिक जानकारी प्रदान करने वाला मन?
१२:१२ बजे पिथिकोस

10

न्यूनतम रननीय उदाहरण

इसे समझने के लिए, आपको पेजिंग की मूल बातों को समझना होगा: x86 पेजिंग कैसे काम करता है? और विशेष रूप से इससे पहले कि यह वास्तव में रैम या डिस्क (आरएसएस निवासी मेमोरी) पर एक बैकिंग स्टोरेज है (ओएस वीज़ेड वर्चुअल मेमोरी) पेज टेबल के माध्यम से वर्चुअल मेमोरी को ओएस आवंटित कर सकता है।

अब इस क्रिया को देखने के लिए, आइए एक कार्यक्रम बनाएं:

  • हमारी भौतिक मेमोरी की तुलना में अधिक RAM आवंटित करता है 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;
}

गिटहब ऊपर

संकलित करें और चलाएं:

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 मेरे कंप्यूटर की भौतिक RAM 32GiB है
  • 0x200000000 == 8GiB: प्रत्येक 8GiB पर मेमोरी प्रिंट करें, इसलिए हमें 32GB पर दुर्घटना से पहले 4 प्रिंट प्राप्त करने चाहिए
  • echo 1 | sudo tee /proc/sys/vm/overcommit_memory: लिनक्स के लिए आवश्यक है कि हम भौतिक रैम की तुलना में एक एमएमएपी कॉल करने की अनुमति दें: अधिकतम मेमोरी जिसे मॉलोक आवंटित कर सकता है

कार्यक्रम का उत्पादन:

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 है , जिसे लिनक्स आउट-ऑफ-मेमोरी किलर द्वारा भेजा जाता है ।

आउटपुट व्याख्या:

  • VSZ वर्चुअल मेमोरी mmap के बाद printf '0x%X\n' 0x40009A4 KiB ~= 64GiB( psमान KiB में हैं) पर स्थिर रहती है ।
  • RSS "वास्तविक मेमोरी उपयोग" केवल पृष्ठों को छूने पर ही आलस्य बढ़ता है। उदाहरण के लिए:
    • पहले प्रिंट पर, हमारे पास है extra_memory_committed 0, जिसका अर्थ है कि हमने अभी तक किसी भी पृष्ठ को नहीं छुआ है। RSS एक छोटा सा है 1648 KiBजिसे सामान्य प्रोग्राम स्टार्टअप जैसे टेक्स्ट एरिया, ग्लोबल्स आदि के लिए आवंटित किया गया है।
    • दूसरे प्रिंट पर, हमने 8388608 KiB == 8GiBपृष्ठों के लायक लिखा है । परिणामस्वरूप, RSS ठीक 8GIB तक बढ़ गया8390256 KiB == 8388608 KiB + 1648 KiB
    • RSS 8GiB वेतन वृद्धि में वृद्धि जारी है। अंतिम प्रिंट में लगभग 24 GiB की मेमोरी दिखाई देती है, और 32 GiB को प्रिंट करने से पहले, OOM किलर ने इस प्रक्रिया को मार दिया

इसे भी देखें: /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

तो हम देखते हैं कि दिलचस्प बात यह थी कि मोंगोबडी डेमॉन हमेशा पृष्ठभूमि में मेरे लैपटॉप में चलता है जो पहले ओओएम किलर को ट्रिगर करता था, संभवतः जब खराब चीज कुछ मेमोरी आवंटित करने की कोशिश कर रही थी।

हालाँकि, 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

और इस बार इसने कुछ क्रोमियम प्रक्रिया को मार दिया, जो कि आमतौर पर मेरा कंप्यूटर सामान्य मेमोरी हॉग है:

[ 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

उबंटू 19.04, लिनक्स कर्नेल 5.0.0 में परीक्षण किया गया।


8

मुझे लगता है कि RSS बनाम VSZ के बारे में पहले ही बहुत कुछ कहा जा चुका है। एक प्रशासक / प्रोग्रामर / उपयोगकर्ता के दृष्टिकोण से, जब मैं डिज़ाइन / कोड अनुप्रयोगों को आरएसजेड, (रेजिडेंट मेमोरी) के बारे में अधिक चिंतित करता हूं, जब और जब आप अधिक से अधिक चर (ढेर) खींचते रहते हैं, तो आप इस मूल्य को शूटिंग करते देखेंगे। लूप में मॉलॉक आधारित अंतरिक्ष आवंटन का निर्माण करने के लिए एक सरल कार्यक्रम का प्रयास करें, और सुनिश्चित करें कि आप उस मॉलोकॉइड स्पेस में डेटा भरेंगे। RSS आगे बढ़ता रहता है। जहां तक ​​वीएसजेड का सवाल है, यह वर्चुअल मेमोरी मैपिंग का अधिक हिस्सा है जो लिनक्स करता है, और इसकी एक मुख्य विशेषता पारंपरिक ऑपरेटिंग सिस्टम अवधारणाओं से निकली है। VSZ प्रबंधन कर्नेल के वर्चुअल मेमोरी प्रबंधन द्वारा किया जाता है, VSZ के बारे में अधिक जानकारी के लिए, mm_struct और vm_struct पर रॉबर्ट लव का विवरण देखें, जो कर्नेल में डेटा के मूल कार्य_ संरचना का हिस्सा हैं।


क्या आप लव द्वारा "लिनक्स कर्नेल डेवलपमेंट" पुस्तक की चर्चा कर रहे हैं?
बेंजामिन

1

वे प्रबंधित नहीं हैं, लेकिन मापा और संभवतः सीमित हैं ( getrlimitसिस्टम कॉल देखें , गेटलिमेलिट (2) पर भी )।

RSS का अर्थ है निवासी सेट आकार (RAM में आपके वर्चुअल एड्रेस स्पेस का हिस्सा)।

आप क्वेरी कर सकता है वर्चुअल ऐड्रेस स्पेस का उपयोग कर प्रक्रिया 1234 proc (5) के साथ cat /proc/1234/mapsके माध्यम से और (स्मृति की खपत सहित) में अपनी स्थितिcat /proc/1234/status


1
हालांकि यह लिंक प्रश्न का उत्तर दे सकता है, लेकिन उत्तर के आवश्यक भागों को शामिल करना और संदर्भ के लिए लिंक प्रदान करना बेहतर है। लिंक-केवल उत्तर अमान्य हो सकते हैं यदि लिंक किए गए पृष्ठ बदल जाते हैं। - समीक्षा से
माक

मैंने एक दूसरी कड़ी प्रदान की। उनमें से एक वैध रहेगा
बेसिल स्टारीनेविच
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.