2008-09-22 17 views
36

'पीएस' और 'टॉप' जैसे उपकरण विभिन्न प्रकार के मेमोरी उपयोग, जैसे वीएम आकार और निवासी सेट आकार की रिपोर्ट करते हैं। हालांकि, उनमें से कोई भी "वास्तविक" स्मृति उपयोग नहीं है:एक प्रक्रिया के "असली" स्मृति उपयोग को निर्धारित करने का एक तरीका, यानी निजी गंदे आरएसएस?

  • प्रोग्राम कोड एक ही प्रोग्राम के कई उदाहरणों के बीच साझा किया जाता है।
  • साझा लाइब्रेरी प्रोग्राम कोड उस लाइब्रेरी का उपयोग करने वाली सभी प्रक्रियाओं के बीच साझा किया जाता है।
  • कुछ ऐप्स प्रक्रियाओं को बंद कर देते हैं और उनके साथ मेमोरी साझा करते हैं (उदा। साझा मेमोरी सेगमेंट के माध्यम से)।
  • वर्चुअल मेमोरी सिस्टम वीएम आकार की रिपोर्ट को काफी बेकार बनाता है।
  • आरएसएस 0 है जब एक प्रक्रिया को बदल दिया जाता है, जिससे यह बहुत उपयोगी नहीं होता है।
  • आदि आदि

मैं पाया है कि निजी गंदा आरएसएस, के रूप में लिनक्स द्वारा रिपोर्ट, "असली" स्मृति के उपयोग के लिए निकटतम बात है। यह /proc/somepid/smaps में सभी Private_Dirty मानों को जोड़कर प्राप्त किया जा सकता है।

हालांकि, अन्य ऑपरेटिंग सिस्टम समान कार्यक्षमता प्रदान करते हैं? यदि नहीं, तो विकल्प क्या हैं? विशेष रूप से, मुझे फ्रीबीएसडी और ओएस एक्स में दिलचस्पी है।

+0

वास्तव में "वास्तविक स्मृति उपयोग" क्या है दे देंगे? आपकी सूची के आधार पर, एकल प्रक्रिया के लिए स्मृति उपयोग का विचार या तो बेकार या मनमाना है। – BCS

+2

मैं "वास्तविक स्मृति उपयोग" को भौतिक स्मृति की मात्रा (लेकिन स्वैप नहीं) के रूप में परिभाषित करता हूं जो कि अगर मैं 'मार -9' दी गई प्रक्रिया को छोड़ दूंगा। मेरा मानना ​​है कि यह संख्या किसी प्रक्रिया के लिए आरएसएस और पीएसएस मूल्यों के बीच कहीं कहीं होनी चाहिए। –

+0

@ हांगली: हालांकि एक पुराना धागा है, मैं आश्चर्यचकित हूं कि क्यों लिनप्रोकस फ्रीबीएसडी के लिए यहां किसी भी व्यक्ति द्वारा सुझाए गए समाधान का हिस्सा नहीं था। क्या इसके लिए कोई विशिष्ट कारण है? मैंने वैसे भी पूरा होने के लिए उस उत्तर को जोड़ा है। – Arvind

उत्तर

3

शीर्ष जानता है कि यह कैसे करें। यह डेबियन लिनक्स पर डिफ़ॉल्ट रूप से वीआईआरटी, आरईएस और एसएचआर दिखाता है। वीआईआरटी = एसडएपी + आरईएस। आरईएस = कोड + डेटा। एसएचआर वह स्मृति है जिसे किसी अन्य प्रक्रिया (साझा लाइब्रेरी या अन्य मेमोरी) के साथ साझा किया जा सकता है।

इसके अलावा, 'गंदा' स्मृति केवल आरईएस मेमोरी है जिसका उपयोग किया गया है, और/या स्वैप नहीं किया गया है।

यह कहना मुश्किल हो सकता है, लेकिन समझने का सबसे अच्छा तरीका यह है कि स्वैपिंग न करने वाली प्रणाली को देखना है। फिर, आरईएस - एसएचआर प्रक्रिया विशेष स्मृति है। हालांकि, यह देखने का एक अच्छा तरीका नहीं है, क्योंकि आप नहीं जानते कि एसएचआर में स्मृति का उपयोग किसी अन्य प्रक्रिया द्वारा किया जा रहा है। यह अनचाहे साझा ऑब्जेक्ट पृष्ठों का प्रतिनिधित्व कर सकता है जिनका उपयोग केवल प्रक्रिया द्वारा किया जाता है।

+0

मुझे नहीं लगता कि यह सही है। Http://pastie.org/277766 पर विचार करें यह पता 300 एमबी पता स्थान में है, लेकिन केवल अंतिम बाइट लिखा गया है। उस ब्लॉक के लिए वास्तविक स्मृति उपयोग 4 केबी (एक पृष्ठ का आकार) होना चाहिए। असली प्रक्रिया मेमोरी उपयोग केवल कई केबी होना चाहिए। – Hongli

+0

आपके उदाहरण में कोई भी अप्रयुक्त स्मृति अभी भी वीआईआरटी कुल में दिखाई देगी। और आरईएस कुल किसी भी अप्रयुक्त स्मृति को प्रतिबिंबित करेगा (यानी, इसे दिखाएं नहीं।) कम से कम, ऐसा लगता है कि यह डेबियन x86 पर काम करता है। – Chris

+0

मैं आपसे सहमत हूं। आरईएस-एसएचआर अधिकांश प्रक्रियाओं के लिए प्रक्रिया मेमोरी उपयोग का मूल्यांकन करने का एक अच्छा तरीका होगा। आम तौर पर मेमोरी लीक निजी मेमोरी में होती है और यही वह जांच है जो आप जांच करेंगे। अगर कोई पूर्ण मेमोरी उपयोग जानना चाहता है तो उसे प्रक्रियाओं को पूरा नहीं करना चाहिए बल्कि समग्र रूप से शीर्ष/htop पर जाना चाहिए। – norekhov

4

आप वास्तव में नहीं कर सकते हैं।

मेरा मतलब है, प्रक्रियाओं के बीच साझा स्मृति ... क्या आप इसे गिनने जा रहे हैं या नहीं। यदि आप इसे गिनते नहीं हैं, तो आप गलत हैं; सभी प्रक्रियाओं के स्मृति उपयोग का योग कुल स्मृति उपयोग नहीं होने वाला है। यदि आप इसे गिनते हैं, तो आप इसे दो बार गिनने जा रहे हैं- योग सही नहीं होगा।

मी, मैं आरएसएस से खुश हूं। और यह जानकर कि आप वास्तव में पूरी तरह से इस पर भरोसा नहीं कर सकते ...

35

ओएसएक्स पर गतिविधि मॉनिटर आपको वास्तव में एक बहुत अच्छा अनुमान देता है।

निजी मेमोरी निश्चित स्मृति के लिए है जो केवल आपके आवेदन द्वारा उपयोग की जाती है। जैसे स्टेक मेमोरी और सभी मेमोरी गतिशील रूप से malloc() और तुलनीय कार्यों/विधियों (उद्देश्य-सी के लिए आवंट विधि) का उपयोग करके आरक्षित निजी स्मृति है। यदि आप कांटा, निजी स्मृति आपके बच्चे के साथ साझा की जाएगी, लेकिन कॉपी-ऑन-राइट चिह्नित है। इसका अर्थ यह है कि जब तक किसी पृष्ठ को किसी भी प्रक्रिया (माता-पिता या बच्चे) द्वारा संशोधित नहीं किया जाता है, तब तक यह उनके बीच साझा किया जाता है। जैसे ही प्रक्रिया किसी भी पृष्ठ को संशोधित करती है, इस पृष्ठ को संशोधित करने से पहले इसकी प्रतिलिपि बनाई जाती है। यहां तक ​​कि यह स्मृति फोर्क बच्चों के साथ साझा की जाती है (और यह केवल कांटा बच्चों के साथ साझा किया जा सकता है), यह अभी भी "निजी" स्मृति के रूप में दिखाया गया है, क्योंकि सबसे बुरे मामले में, इसका प्रत्येक पृष्ठ संशोधित हो जाएगा (जल्दी या बाद में) और फिर यह फिर से प्रत्येक प्रक्रिया के लिए निजी है।

साझा स्मृति या तो स्मृति जो वर्तमान में साझा की गई है (उसी पृष्ठ को विभिन्न प्रक्रियाओं की वर्चुअल प्रोसेस स्पेस में दिखाई दे रहा है) या भविष्य में साझा होने की संभावना है (उदाहरण के लिए केवल पढ़ने की स्मृति, क्योंकि कोई कारण नहीं है केवल पढ़ने के लिए स्मृति साझा नहीं करने के लिए)। कम से कम इस तरह मैं ऐप्पल से कुछ कमांड लाइन टूल्स के स्रोत कोड को पढ़ता हूं। तो यदि आप mmap (या तुलनात्मक कॉल जो एक ही मेमोरी को एकाधिक प्रक्रियाओं में मैप करते हैं) का उपयोग करके प्रक्रियाओं के बीच स्मृति साझा करते हैं, तो यह साझा स्मृति होगी। हालांकि निष्पादन योग्य कोड स्वयं भी स्मृति साझा किया जाता है, क्योंकि यदि आपके आवेदन का एक और उदाहरण शुरू हो गया है, तो ऐसा कोई कारण नहीं है कि यह पहले से ही स्मृति में लोड किए गए कोड को साझा नहीं कर सकता है (निष्पादन योग्य कोड पृष्ठ केवल डिफ़ॉल्ट रूप से पढ़े जाते हैं, जब तक कि आप अपना भाग नहीं लेते एक डीबगर में ऐप)। इस प्रकार साझा मेमोरी वास्तव में आपके एप्लिकेशन द्वारा उपयोग की जाने वाली मेमोरी है, बस निजी की तरह, लेकिन इसे अतिरिक्त रूप से किसी अन्य प्रक्रिया के साथ साझा किया जा सकता है (या हो सकता है, लेकिन यह आपके आवेदन की ओर क्यों नहीं गिना जाएगा?)

वास्तविक स्मृति आपकी प्रक्रिया में वर्तमान में "असाइन की गई" रैम की मात्रा है, चाहे कोई भी निजी या साझा न हो। यह वास्तव में निजी और साझा की राशि हो सकती है, लेकिन आमतौर पर यह नहीं है। वर्तमान में इसकी आवश्यकता के मुकाबले आपकी प्रक्रिया में अधिक स्मृति आवंटित हो सकती है (यह भविष्य में अधिक स्मृति के लिए अनुरोधों को गति देता है), लेकिन यह सिस्टम को कोई नुकसान नहीं है। यदि सिस्टम को स्वैपिंग शुरू होने से पहले किसी अन्य प्रक्रिया को मेमोरी की आवश्यकता होती है और कोई भी मुफ्त मेमोरी उपलब्ध नहीं होती है, तो यह अतिरिक्त प्रक्रिया को आपकी प्रक्रिया से दूर ले जाएगी और इसे एक और प्रक्रिया सौंपेगी (जो एक तेज़ और दर्द रहित ऑपरेशन है); इसके लिए आपकी अगली मॉलोक कॉल कुछ हद तक धीमी हो सकती है। वास्तविक स्मृति निजी और भौतिक स्मृति से भी छोटी हो सकती है; ऐसा इसलिए है क्योंकि यदि आपकी प्रक्रिया सिस्टम से स्मृति का अनुरोध करती है, तो इसे केवल "वर्चुअल मेमोरी" प्राप्त होगी। जब तक आप इसका उपयोग नहीं करते हैं, तब तक यह वर्चुअल मेमोरी किसी भी वास्तविक मेमोरी पेज से जुड़ी नहीं है (इसलिए मैलोक 10 एमबी मेमोरी, इसके केवल एक बाइट का उपयोग करें, आपकी प्रक्रिया को केवल एक ही पेज, 4096 बाइट, स्मृति आवंटित किया जाएगा - शेष केवल तभी असाइन किया जाता है जब आपको वास्तव में इसकी आवश्यकता हो)। स्वैप की गई अतिरिक्त मेमोरी वास्तविक स्मृति की ओर गिनती नहीं कर सकती है (इस बारे में निश्चित नहीं है), लेकिन यह साझा और निजी मेमोरी की ओर गिना जाएगा।

वर्चुअल मेमोरी उन सभी पता ब्लॉकों का योग है जो आपके ऐप्स प्रक्रिया स्थान में मान्य मानी जाती हैं। ये पते भौतिक स्मृति से जुड़ा हो सकता है (जो कि फिर से निजी या साझा किया जाता है), या वे शायद नहीं, लेकिन उस स्थिति में जैसे ही आप पते का उपयोग करते हैं, वे भौतिक स्मृति से जुड़े रहेंगे। ज्ञात पतों के बाहर मेमोरी पतों तक पहुंचने से सिगबस हो जाएगा और आपका ऐप क्रैश हो जाएगा। जब स्मृति बदली है, यह स्मृति के लिए वर्चुअल ऐड्रेस स्पेस मान्य रहती है और उन पतों तक पहुँचने का कारण बनता है स्मृति में वापस बदली किए जाने की

निष्कर्ष:।
अपने अनुप्रयोग स्पष्ट या परोक्ष साझा स्मृति का उपयोग नहीं करता है, तो निजी स्मृति स्टैक आकार (या मल्टीथ्रेड किए गए आकार) के कारण आपके ऐप की मेमोरी की मात्रा है और मॉलोक() कॉल की वजह से आपने गतिशील मेमोरी के लिए बनाया है। उस मामले में आपको साझा या वास्तविक स्मृति के लिए बहुत कुछ परवाह नहीं है।

यदि आपका ऐप साझा मेमोरी का उपयोग करता है, और इसमें एक ग्राफिकल यूआई शामिल है, जहां उदाहरण के लिए आपके एप्लिकेशन और विंडोसेवर के बीच मेमोरी साझा की जाती है, तो हो सकता है कि आप साझा स्मृति को भी देखें। एक बहुत ही उच्च साझा स्मृति संख्या का मतलब हो सकता है कि इस समय आपके पास स्मृति में लोड किए गए बहुत से ग्राफिकल संसाधन हैं।

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

आप अभी भी है कि सभी जानकारी से खुश नहीं हैं, तो आप भी अधिक जानकारी प्राप्त कर सकते हैं। टर्मिनल खोलें और चलाएं:

sudo vmmap <pid> 

आपकी प्रक्रिया की प्रक्रिया आईडी कहां है। यह हर आरंभ और अंत पते के साथ अपने प्रक्रिया अंतरिक्ष में स्मृति के ब्लॉक के लिए आप के आंकड़े दिखाएगी। यह भी आपको बता देंगे, जहां इस स्मृति से आया है (ए मैप की फ़ाइल? स्मृति स्टैक? Malloc'ed स्मृति? अपने निष्पादन का एक __DATA या __TEXT अनुभाग?), कितना बड़ा यह KB में है, अधिकारों का उपयोग और क्या यह निजी है, साझा या कॉपी-ऑन-राइट। यदि यह किसी फ़ाइल से मैप किया गया है, तो यह आपको फ़ाइल का मार्ग भी देगा।

आप केवल "वास्तविक" RAM उपयोग करना चाहते हैं, का उपयोग

sudo vmmap -resident <pid> 

अब यह हर स्मृति ब्लॉक के लिए दिखाई देगा कितना बड़ा स्मृति ब्लॉक लगभग है और इसके बारे में कितना वास्तव में वर्तमान में भौतिक स्मृति में मौजूद है।

प्रत्येक डंप के अंत में भी अलग स्मृति प्रकार की रकम के साथ एक सिंहावलोकन तालिका है। यह तालिका अभी मेरे सिस्टम पर फ़ायरफ़ॉक्स के लिए इस तरह दिखती है:

REGION TYPE    [ VIRTUAL/RESIDENT] 
===========    [ =======/========] 
ATS (font support)  [ 33.8M/ 2496K] 
CG backing stores  [ 5588K/ 5460K] 
CG image    [  20K/  20K] 
CG raster data   [ 576K/ 576K] 
CG shared images  [ 2572K/ 2404K] 
Carbon     [ 1516K/ 1516K] 
CoreGraphics   [  8K/  8K] 
IOKit     [ 256.0M/  0K] 
MALLOC     [ 256.9M/ 247.2M] 
Memory tag=240   [  4K/  4K] 
Memory tag=242   [  12K/  12K] 
Memory tag=243   [  8K/  8K] 
Memory tag=249   [ 156K/  76K] 
STACK GUARD    [ 101.2M/ 9908K] 
Stack     [ 14.0M/ 248K] 
VM_ALLOCATE    [ 25.9M/ 25.6M] 
__DATA     [ 6752K/ 3808K] 
__DATA/__OBJC   [  28K/  28K] 
__IMAGE     [ 1240K/ 112K] 
__IMPORT    [ 104K/ 104K] 
__LINKEDIT    [ 30.7M/ 3184K] 
__OBJC     [ 1388K/ 1336K] 
__OBJC/__DATA   [  72K/  72K] 
__PAGEZERO    [  4K/  0K] 
__TEXT     [ 108.6M/ 63.5M] 
__UNICODE    [ 536K/ 512K] 
mapped file    [ 118.8M/ 50.8M] 
shared memory   [ 300K/ 276K] 
shared pmap    [ 6396K/ 3120K] 

यह हमें क्या बताता है? जैसे फ़ायरफ़ॉक्स बाइनरी और लोड होने वाली सभी लाइब्रेरी में उनके __TEXT अनुभागों में 108 एमबी डेटा एक साथ है, लेकिन वर्तमान में उनमें से केवल 63 एमबी स्मृति में निवासी हैं। फ़ॉन्ट समर्थन (एटीएस) को 33 एमबी की आवश्यकता है, लेकिन केवल 2.5 एमबी वास्तव में स्मृति में हैं। यह 5 एमबी सीजी बैकिंग स्टोर्स, सीजी = कोर ग्राफिक्स से थोड़ा अधिक उपयोग करता है, जो सबसे अधिक संभावना खिड़की सामग्री, बटन, छवियों और अन्य डेटा हैं जो तेजी से ड्राइंग के लिए कैश किए जाते हैं। उसने मॉलोक कॉल के माध्यम से 256 एमबी का अनुरोध किया है और वर्तमान में 247 एमबी मेमोरी पेजों में मैप किए गए हैं। इसमें 14 एमबी स्पेस स्टैक्स के लिए आरक्षित है, लेकिन अभी केवल 248 केबी स्टैक स्पेस वास्तव में उपयोग में है।

vmmap भी तालिका

ReadOnly portion of Libraries: Total=139.3M resident=66.6M(48%) swapped_out_or_unallocated=72.7M(52%) 
Writable regions: Total=595.4M written=201.8M(34%) resident=283.1M(48%) swapped_out=0K(0%) unallocated=312.3M(52%) 

ऊपर एक अच्छा सारांश है और यह ओएस एक्स का एक दिलचस्प पहलू पता चलता है: केवल पढ़ने के लिए स्मृति के लिए यह कोई भूमिका निभाता है अगर यह बदली या बस आवंटित नहीं की गई है; केवल निवासी और निवासी नहीं है। लिखने योग्य स्मृति के लिए यह एक फर्क नहीं पड़ता (मेरे मामले में सभी से अनुरोध किया स्मृति के 52% इस्तेमाल किया गया कभी नहीं किया है और इस तरह के आवंटित नहीं की गई है, स्मृति के 0% डिस्क के लिए बदली गई है)

8

लिनक्स पर, आप चाहते हो सकता है पीएसएस (आनुपातिक सेट आकार) संख्या/proc/स्वयं/smaps में संख्या। मैपिंग का पीएसएस आरएसएस है जो उस मैपिंग का उपयोग कर रहे प्रक्रियाओं की संख्या से विभाजित है।

4

आप निजी गंदा और निजी स्वच्छ आरएसएस/proc/पीआईडी ​​/ smaps

0

एक सवाल है कि FreeBSD उल्लेख से, कोई भी हैरान कर प्राप्त कर सकते हैं अभी तक यह लिखा:

आप एक linux शैली/proc चाहते हैं/ProcessID/स्थिति उत्पादन, कृपया निम्नलिखित करें:

mount -t linprocfs none /proc 
cat /proc/PROCESSID/status 

FreeBSD 7.0 में कम से कम, लगाने डिफ़ॉल्ट (7 द्वारा नहीं किया गया था।0,

1
for i in /proc/[0-9]*; do 
    grep -q 'Private_Dirty' $i/smaps; 
    if [ $? -ne 0 ]; then 
    continue; 
    fi; 
    echo -n "${i}: "; 
    awk '/Private_Dirty/ {print $2,$3}' $i/smaps | 
    sed 's/ tB/*1024 gB/;s/ gB/*1024 mB/;s/ mB/*1024 kB/;s/ kB/*1024/;1!s/^/+/;' | 
    tr -d '\n' | 
    sed 's/$/\n/' | 
    bc | 
    tr -d '\n'; 
    echo; 
done | 
sort -n -k 2 
0

इसे देखें, इस सूक्ति-प्रणाली की निगरानी के स्रोत कोड है एक बहुत पुराना रिलीज है, लेकिन कुछ इस बुनियादी के लिए, इस सवाल का जवाब एक मेलिंग सूची में छिपा हुआ था!) ​​यह स्मृति सोचता है "वास्तव में इस्तेमाल किया" के बाद एक प्रक्रिया X सर्वर मेमोरी का योग (info->mem) (info->memxserver) और लिखने योग्य मेमोरी (info->memwritable) है, "लिखने योग्य मेमोरी" स्मृति ब्लॉक जो "Private_Dirty" चिह्नित कर रहे हैं है /proc/pID/smaps फ़ाइल में।

लिनक्स सिस्टम के अलावा, gnome-system-monitor कोड के अनुसार अलग-अलग तरीका हो सकता है।

static void 
get_process_memory_writable (ProcInfo *info) 
{ 
    glibtop_proc_map buf; 
    glibtop_map_entry *maps; 

    maps = glibtop_get_proc_map(&buf, info->pid); 

    gulong memwritable = 0; 
    const unsigned number = buf.number; 

    for (unsigned i = 0; i < number; ++i) { 
#ifdef __linux__ 
     memwritable += maps[i].private_dirty; 
#else 
     if (maps[i].perm & GLIBTOP_MAP_PERM_WRITE) 
      memwritable += maps[i].size; 
#endif 
    } 

    info->memwritable = memwritable; 

    g_free(maps); 
} 

static void 
get_process_memory_info (ProcInfo *info) 
{ 
    glibtop_proc_mem procmem; 
    WnckResourceUsage xresources; 

    wnck_pid_read_resource_usage (gdk_screen_get_display (gdk_screen_get_default()), 
            info->pid, 
            &xresources); 

    glibtop_get_proc_mem(&procmem, info->pid); 

    info->vmsize = procmem.vsize; 
    info->memres = procmem.resident; 
    info->memshared = procmem.share; 

    info->memxserver = xresources.total_bytes_estimate; 

    get_process_memory_writable(info); 

    // fake the smart memory column if writable is not available 
    info->mem = info->memxserver + (info->memwritable ? info->memwritable : info->memres); 
} 
संबंधित मुद्दे