लिनक्स में स्मृति उपयोग को सही ढंग से निर्धारित करना


63

मैं कुछ परिणामों पर उलझन में हूँ, जिन्हें मैं ps और free से देख रहा हूँ ।

मेरे सर्वर पर, यह परिणाम है free -m

[root@server ~]# free -m
             total       used       free     shared    buffers     cached
Mem:          2048       2033         14          0         73       1398
-/+ buffers/cache:        561       1486
Swap:         2047         11       2036

लिनक्स कैसे मेमोरी का प्रबंधन करता है, इसकी मेरी समझ यह है कि यह रैम में डिस्क के उपयोग को संग्रहीत करेगा, ताकि प्रत्येक बाद की पहुंच जल्दी हो। मेरा मानना ​​है कि यह "कैश्ड" कॉलम द्वारा इंगित किया गया है। इसके अतिरिक्त, विभिन्न बफ़र्स को रैम में संग्रहीत किया जाता है, जो "बफ़र्स" कॉलम में दर्शाया गया है।

इसलिए अगर मैं सही तरीके से समझूं, तो "वास्तविक" उपयोग को "-" + + बफ़र्स / कैश ", या इस मामले में 561" का "उपयोग" मूल्य माना जाता है।

इसलिए यह मानना ​​कि यह सब सही है, जो हिस्सा मुझे फेंकता है, उसी का परिणाम है ps aux

psपरिणामों के बारे में मेरी समझ यह है कि 6 वां कॉलम (RSS), किलोबाइट्स में आकार का प्रतिनिधित्व करता है जो प्रक्रिया मेमोरी के लिए उपयोग करती है।

इसलिए जब मैं यह कमांड चलाता हूं:

[root@server ~]# ps aux | awk '{sum+=$6} END {print sum / 1024}'
1475.52

क्या परिणाम "/ + बफ़र्स / कैश" का "उपयोग किया गया" कॉलम नहीं होना चाहिए free -m?

तो, मैं लिनक्स में एक प्रक्रिया के मेमोरी उपयोग को कैसे ठीक से निर्धारित कर सकता हूं? जाहिर तौर पर मेरा तर्क त्रुटिपूर्ण है।


यह प्रश्न काफी लोकप्रिय है और मुझे लगता है कि मुझे htopलेखक के एक जवाब को उसी दिन साझा करना चाहिए जैसा कि मैंने दूसरे दिन किया था ... स्मृति के उपयोग की गणना कैसे करें / proc / meminfo (जैसे htop) से
tgogos

जवाबों:


57

यह ठीक उसी सवाल को दूसरे दिन सर्वरफॉल्ट पर पूछा गया था :-)

लिनक्स वर्चुअल मेमोरी सिस्टम इतना सरल नहीं है। आप बस आरएसएस के सभी क्षेत्रों को जोड़ नहीं सकते हैं और इसके usedद्वारा रिपोर्ट किए गए मूल्य प्राप्त कर सकते हैं free। इसके कई कारण हैं, लेकिन मैं सबसे बड़े लोगों में से एक को मारूंगा।

  • जब कोई प्रक्रिया शुरू होती है, तो माता-पिता और बच्चे दोनों एक ही आरएसएस के साथ दिखेंगे। हालांकि linux copy-on-writeइसलिए कार्यरत है कि दोनों प्रक्रियाएं वास्तव में एक ही मेमोरी का उपयोग कर रही हैं। केवल जब कोई प्रक्रिया स्मृति को संशोधित करती है तो क्या वह वास्तव में दोहराई जाएगी। इस कारण यह freeसंख्या topRSS योग से छोटी होगी ।

  • RSS मान में साझा मेमोरी शामिल नहीं है। क्योंकि साझा मेमोरी किसी एक प्रक्रिया के स्वामित्व में topनहीं है, इसलिए इसे RSS में शामिल नहीं किया जाता है। तो यह आरएसएस की freeसंख्या से बड़ा होने का कारण होगा top


1
यह सबसे अच्छा जवाब है जो मैंने आज तक किसी भी स्टैक-एक्सचेंज साइट पर प्राप्त किया है। इसलिए विशेष रूप से जो मैं जानना चाहता था। यह मेरी स्थिति के लिए विशेष रूप से सटीक है क्योंकि मैं एक कार्यक्रम के साथ काम कर रहा हूं जो मैंने लिखा था कि प्रक्रियाओं के कांटे, लेकिन अधिकांश पदचिह्न पुस्तकालयों में हैं जो वे उपयोग करते हैं।
गोल्डनन्यूबी

इस उत्तर के साथ समस्या यह है कि RSS और SHR की गणना अक्सर उपयोग की गई मेमोरी से बहुत कम होती है। उदाहरण के लिए एक वीपीएस मेरे पास है, उपयोग की गई मेमोरी 380 एमबी है जबकि सभी आरएसएस और एसएचआर का योग 90 एमबी है।
user239558

2
@ user239558 जैसा कि मैंने उत्तर में उल्लेख किया है, कई कारण हैं जो संख्याएँ जोड़ते नहीं हैं, मैंने केवल उनमें से 2 सूचीबद्ध किए हैं। कई अन्य संख्याएं हैं; कैश, स्लैब, विशाल पृष्ठ, आदि
पैट्रिक

2
संभवतः इसके उत्तर देने के वर्षों बाद, मुझे अभी भी (कम से कम) एक भ्रम है। आपने कहा कि RSS मूल्य में साझा मेमोरी शामिल नहीं है, लेकिन इस उत्तर में कहा गया है कि "इसमें साझा पुस्तकालयों से मेमोरी शामिल है, जब तक कि उन पुस्तकालयों के पृष्ठ वास्तव में स्मृति में हैं"। अब मुझे नहीं पता कि किस पर विश्वास करना है ... शायद मुझे यहाँ कुछ सूक्ष्म अंतर याद आ रहे हैं ...
Naitree

1
@ नैत्र "साझा पुस्तकालय"! = "साझा स्मृति"। साझा मेमोरी सामान की तरह है shmgetया mmap। मेमोरी स्टफ के आस-पास का शब्द बहुत पेचीदा है। गलत शब्द का गलत जगह इस्तेमाल करने से वाक्य का अर्थ पूरी तरह से बिगड़ सकता है।
पैट्रिक

30

यदि आप मेमोरी नंबर की तलाश कर रहे हैं, तो smem पर एक नज़र है :

smem एक ऐसा उपकरण है जो Linux सिस्टम पर मेमोरी उपयोग पर कई रिपोर्ट दे सकता है। मौजूदा साधनों के विपरीत, smem आनुपातिक सेट आकार (PSS) की रिपोर्ट कर सकता है, जो कि एक वर्चुअल मेमोरी सिस्टम में पुस्तकालयों और अनुप्रयोगों द्वारा उपयोग की जाने वाली स्मृति की मात्रा का अधिक सार्थक प्रतिनिधित्व है।

क्योंकि भौतिक मेमोरी के बड़े हिस्से आम तौर पर कई अनुप्रयोगों के बीच साझा किए जाते हैं, निवासी सेट आकार (आरएसएस) के रूप में ज्ञात मेमोरी उपयोग के मानक माप महत्वपूर्ण रूप से स्मृति उपयोग को अधिलेखित करेंगे। पीएसएस इसके बजाय यथार्थवादी माप देने के लिए प्रत्येक साझा क्षेत्र के प्रत्येक एप्लिकेशन के "उचित शेयर" को मापता है।

यहाँ उदाहरण के लिए:

# smem -t
  PID User     Command                         Swap      USS      PSS      RSS
...
10593 root     /usr/lib/chromium-browser/c        0    22868    26439    49364 
11500 root     /usr/lib/chromium-browser/c        0    22612    26486    49732 
10474 browser  /usr/lib/chromium-browser/c        0    39232    43806    61560 
 7777 user     /usr/lib/thunderbird/thunde        0    89652    91118   102756 
-------------------------------------------------------------------------------
  118 4                                       40364   594228   653873  1153092 

तो PSSयहाँ दिलचस्प स्तंभ है क्योंकि यह साझा मेमोरी को ध्यान में रखता है।
इसके विपरीत RSSइसे जोड़ना सार्थक है। हमें यहां उपयोगकर्ता प्रक्रियाओं के लिए 654Mb कुल मिला है।

सिस्टम-वाइड आउटपुट बाकी के बारे में बताता है:

# smem -tw
Area                           Used      Cache   Noncache 
firmware/hardware                 0          0          0 
kernel image                      0          0          0 
kernel dynamic memory        345784     297092      48692 
userspace memory             654056     181076     472980 
free memory                   15828      15828          0 
----------------------------------------------------------
                            1015668     493996     521672 

तो 1 जीबी रैम कुल = 654 एमबी उपयोगकर्ता की प्रक्रिया + 346 एमबी कर्नेल मेम + 16 एमबी मुफ्त
(कुछ एमबी दें या लें)

कुल मिलाकर लगभग आधी मेमोरी कैश (494Mb) के लिए उपयोग की जाती है।

बोनस प्रश्न : यहाँ उपयोगकर्ता कैश बनाम कर्नेल कैश क्या है?


कुछ दृश्य की कोशिश के लिए btw:

# smem  --pie=name

यहाँ छवि विवरण दर्ज करें


14

वास्तव में एक अच्छा उपकरण है pmapजो एक निश्चित प्रक्रिया के लिए मेमोरी के वर्तमान उपयोग को सूचीबद्ध करता है :

pmap -d PID

इसके बारे में अधिक जानकारी के लिए मैन पेज देखें man pmapऔर 20 लिनक्स सिस्टम मॉनिटरिंग टूल्स पर भी एक नजर डालें ।


यह एक बहुत अच्छा उपकरण है, लेकिन यह वास्तव में मेरी समस्या का समाधान नहीं करता है। मैं यह पता लगाने की कोशिश कर रहा हूं कि सर्वर पर "वास्तविक" मेमोरी उपयोग को प्रभावी ढंग से कैसे निर्धारित किया जाए।
गोल्डननबी

3
@GoldenNewby किसी प्रक्रिया की "वास्तविक" मेमोरी उपयोग जैसी कोई चीज नहीं है। सिस्टम का वास्तविक मेमोरी उपयोग वही है जो freeआपको बताता है।
गाइल्स

pmap -x PIDइसमें एक RSS कॉलम भी शामिल है जो अक्सर विचार प्राप्त करने के लिए काफी उपयोगी होता है जहाँ RSS एक प्रक्रिया का योग होता है (जैसा कि उदाहरण के माध्यम से देखा जाता है top)।
maxschlepzig

10

शीर्ष भागो, hमदद के लिए मारा फिर fखेतों को जोड़ने के लिए। आप निम्नलिखित फ़ील्ड जोड़ सकते हैं:

  • RSS भौतिक मेमोरी की मात्रा जो अनुप्रयोग उपयोग कर रहा है
  • CODE स्मृति की कुल मात्रा प्रक्रिया का निष्पादन योग्य कोड उपयोग कर रही है
  • DATA - स्मृति की कुल मात्रा (kb) एक प्रक्रिया के डेटा और स्टैक के लिए समर्पित

इन 3 के बीच आपके पास बहुत सटीक परिणाम होने चाहिए। आप मेरे द्वारा सुझाए गए शीर्ष htopया के लिए अधिक विस्तृत प्रतिस्थापन का उपयोग कर सकते हैं atop

संपादित करें: यदि आप वास्तव में विस्तृत जानकारी चाहते हैं तो लगभग भूल गए हैं। PID ढूँढें और निम्न फ़ाइल बिल्ली।

PID=123

cat /proc/123/status

संपादित करें 2: यदि आप इसे पा सकते हैं या यह पुस्तक है:

लिनक्स प्रदर्शन का अनुकूलन: लिनक्स प्रदर्शन उपकरण के लिए एक हैंड्स-ऑन गाइड

-एक खंड अध्याय 5: प्रदर्शन उपकरण: प्रक्रिया-विशिष्ट मेमोरी -इसमें आपके द्वारा कभी भी चाहने से अधिक जानकारी है।


डिफ़ॉल्ट रूप से शीर्ष पर आरएसएस की प्रक्रिया का आकार होता है। शीर्ष मेरे उदाहरण में "ps aux" के समान परिणाम देता है। मेरा प्रश्न है, यह कैसे है कि सभी प्रक्रियाओं का संयुक्त आरएसएस पूरे सर्वर पर "सक्रिय" मेमोरी उपयोग की तुलना में बहुत अधिक है?
गोल्डन नब्बे

5

psआपको प्रत्येक प्रक्रिया द्वारा उपयोग की जाने वाली मेमोरी की मात्रा देता है। उस मेमोरी में से कुछ mmapped फाइलें हैं, जो कैश के अंतर्गत आती हैं। कुछ मेमोरी (विशेष रूप से कोड) को अन्य प्रक्रियाओं के साथ साझा किया जाता है, इसलिए यदि आप आरएसएस मूल्यों को जोड़ते हैं तो इसे कई बार गिना जाता है।

"इस प्रक्रिया का उपयोग कितनी मेमोरी करता है?" का कोई सही उत्तर नहीं है, क्योंकि यह अकेले प्रक्रिया पर निर्भर नहीं करता है, यह पर्यावरण पर भी निर्भर करता है। कई अलग-अलग मूल्य हैं जिन्हें आप प्रक्रिया का "मेमोरी उपयोग" कह सकते हैं, और वे अलग-अलग चीजों की गिनती कर रहे हैं क्योंकि वे मेल नहीं खाते या जोड़ते नहीं हैं।


4

जैसा कि अन्य लोगों ने सही ढंग से बताया है, एक प्रक्रिया द्वारा उपयोग की जाने वाली वास्तविक मेमोरी पर एक हैंडल प्राप्त करना कठिन है, जो साझा क्षेत्रों और mmap'ed फ़ाइलों और whatnot के साथ है।

यदि आप एक प्रयोगकर्ता हैं, तो आप वेलग्रिंड और मासिफ चला सकते हैं । यह आकस्मिक उपयोगकर्ता के लिए थोड़ा भारी हो सकता है लेकिन आपको समय के साथ किसी एप्लिकेशन के मेमोरी व्यवहार का अंदाजा हो जाएगा। यदि एक आवेदन मॉलोक () की वास्तव में इसकी आवश्यकता है तो यह आपको एक प्रक्रिया के वास्तविक गतिशील स्मृति उपयोग का एक अच्छा प्रतिनिधित्व देगा। लेकिन यह प्रयोग "जहर" हो सकता है।

मामलों को जटिल करने के लिए, लिनक्स आपको अपनी मेमोरी को ओवरकम करने की अनुमति देता है । जब आप मैलोच () मेमोरी करते हैं, तो आप मेमोरी का उपभोग करने के लिए अपना इरादा बता रहे हैं। लेकिन आवंटन वास्तव में तब तक नहीं होता है जब तक आप अपने आवंटित "रैम" के एक नए पृष्ठ में एक बाइट नहीं लिखते हैं। आप इस तरह से एक छोटे सी कार्यक्रम लिखने और चलाने के द्वारा खुद को साबित कर सकते हैं:

// test.c
#include <malloc.h>
#include <stdio.h>
#include <unistd.h>
int main() {
    void *p;
    sleep(5)
    p = malloc(16ULL*1024*1024*1024);
    printf("p = %p\n", p);
    sleep(30);
    return 0;
}

# Shell:
cc test.c -o test && ./test &
top -p $!

16GB से कम रैम वाली मशीन पर इसे चलाएं और वॉयला!, आपने सिर्फ 16GB मेमोरी का स्कोर किया है। (नहीं वास्तव में नहीं)।

नोटिस में topआप "VIRT" को 16.004G के रूप में देखते हैं लेकिन% MEM 0.0 है

इसे फिर से वेलग्रिंड से चलाएं:

# Shell:
valgrind --tool=massif ./test &
sleep 36
ms_print massif.out.$! | head -n 30

और मासिफ कहते हैं "सभी योगों का योग () = 16 जीबी"। इसलिए यह बहुत दिलचस्प नहीं है।

लेकिन, यदि आप एक पर में चलाते हैं तो समझदार प्रक्रिया:

# Shell:
rm test test.o
valgrind --tool=massif cc test.c -o test &
sleep 3
ms_print massif.out.$! | head -n 30

--------------------------------------------------------------------------------
Command:            cc test.c -o test
Massif arguments:   (none)
ms_print arguments: massif.out.23988
--------------------------------------------------------------------------------


    KB
77.33^                                                                       :
     |                                                                      #:
     |                                                                :@::@:#:
     |                                                           :::::@@::@:#:
     |                                                         @:: :::@@::@:#:
     |                                                     ::::@:: :::@@::@:#:
     |                                             ::@:::@:::::@:: :::@@::@:#:
     |                                            @::@:::@:::::@:: :::@@::@:#:
     |                                            @::@:::@:::::@:: :::@@::@:#:
     |                      :@@@@@@@@@@@@@@@@@@@@:@::@:::@:::::@:: :::@@::@:#:
     |                      :@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                    :@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                    :@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                   :@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                   :@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |              :@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |          :::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |        :::::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |       ::::::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |       ::::::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
   0 +----------------------------------------------------------------------->Mi
     0                                                                   1.140

और यहां हम देखते हैं (बहुत अनुभवजन्य और बहुत अधिक आत्मविश्वास के साथ) कि संकलक ने ढेर का 77KB आवंटित किया।

सिर्फ ढेर उपयोग पाने के लिए इतनी मेहनत क्यों करें? क्योंकि सभी साझा किए गए ऑब्जेक्ट और टेक्स्ट सेक्शन जो एक प्रक्रिया का उपयोग करते हैं (इस उदाहरण में, संकलक) बहुत दिलचस्प नहीं हैं। वे एक प्रक्रिया के लिए निरंतर ओवरहेड हैं। वास्तव में, प्रक्रिया के बाद के आक्रमण लगभग "मुक्त" के लिए आते हैं।

इसके अलावा, निम्नलिखित की तुलना करें और इसके विपरीत करें:

MMAP () 1GB फ़ाइल। आपका VMSize 1 + GB होगा। लेकिन आप रेजिडेंट सेट साइज़ केवल उस फ़ाइल के भाग होंगे, जिसके कारण आपको उस क्षेत्र में एक पॉइंटर (dereferencing द्वारा) पृष्ठांकित करने का कारण बना। और यदि आप पूरी फाइल को "पढ़" लेते हैं, तब, जब तक आप अंत तक नहीं पहुंच जाते, तब तक कर्नेल ने पहले ही शुरुआत को रोक दिया होगा (यह करना आसान है क्योंकि कर्नेल को पता है कि उन पृष्ठों को फिर से कैसे / कहाँ से बदलना है अगर फिर से शुरू किया गया हो )। या तो मामले में, न तो VMSize और न ही RSS आपकी मेमोरी "उपयोग" का एक अच्छा संकेतक है। आपने वास्तव में कुछ भी नहीं किया है।

इसके विपरीत, मल्लोक () और स्मृति के बहुत से स्पर्श - जब तक कि आपकी स्मृति डिस्क पर स्वैप नहीं हो जाती। तो आपकी आवंटित मेमोरी अब आपके RSS से अधिक हो गई है। यहां, आपका VMSize आपको कुछ बताना शुरू कर सकता है (आपकी प्रक्रिया वास्तव में आपके रैम में रहने की तुलना में अधिक स्मृति का मालिक है)। लेकिन अभी भी वीएम के बीच अंतर करना मुश्किल है जो साझा किए गए पृष्ठ और वीएम है जो डेटा स्वैप किया गया है।

यह वह जगह है जहाँ वेलग्रिंड / मासिफ दिलचस्प हो जाता है। यह आपको दिखाता है कि आपने जानबूझकर क्या आवंटित किया है (आपके पृष्ठों की स्थिति की परवाह किए बिना)।


मुझे आपके लिए एक प्रश्न मिला है। मुझे एक प्रक्रिया मिली है जो mlock () की सभी mmap'ed फ़ाइलों की है। क्या यह निर्धारित करने का एक तरीका है कि इस मेमोरी का कितना सक्रिय रूप से उपयोग किया जाता है - इसे पिछले मिनट या दो में से कितना पढ़ा या लिखा गया है?
माइकल मार्टिनेज

2

यह कोशिश करें: यह आपको एमबी में चलने वाली सभी प्रक्रिया द्वारा वास्तव में उपयोग की जाने वाली कुल रैम देगा

ps -eo size,pid,user,command --sort -size | awk '
  { hr=$1/1024 ; printf("%13.2f Mb ",hr) } 
  { for ( x=4 ; x<=NF ; x++ ) { printf("%s ",$x) } print "" }
  ' | awk '{total=total + $1} END {print total}'

sizeसूचना द्वारा psवास्तविक स्मृति उपयोग करने के लिए छोटे से संबंध है। यह प्रत्येक प्रक्रिया का आभासी आकार है जो जरूरी नहीं कि मेमोरी आवंटित की गई हो। इसमें कुछ खंड भी शामिल नहीं हैं जिन्हें आवंटित किया गया है।
मैट

-2

यह आपको दिखाता है कि उपयोगकर्ताओं द्वारा कितनी स्मृति उपयोगकर्ता है ..

#!/bin/bash
total_mem=0

printf "%-10s%-10s\n" User MemUsage

while read u m
do
        [[ $old_user != $u ]] && {  printf "%-10s%-0.1f\n" $old_user $total_mem;
                                    total_mem=0; }
        total_mem="$(echo $m + $total_mem | bc)"
        old_user=$u

done < <(ps --no-headers -eo user,%mem| sort -k1)

#EOF

-3

% में मेमोरी का उपयोग खोजने के लिए इस कमांड का उपयोग करें।

मेमोरी का उपयोग:

grep Mem | awk '{print $3/$2 * 100.0}'

फ्री मेमोरी

grep Mem | awk '{print $4/$2 * 100.0}'

3
इर्र, यह कुछ भी नहीं करेगा। grepवहाँ बस इनपुट के इंतजार में बैठेंगे।
Mattdm

1
यह होना चाहिए थाfree -m | grep Mem | awk '{print $3/$2 * 100.0}'
vjangus
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.