2012-11-21 10 views
12

मुझे अपने कोड के साथ निम्नलिखित समस्याएं आईं: मैं वैप चेकिंग और हेप प्रोफाइलिंग करने के लिए वालग्रींड और गैपरफेटोल का उपयोग कर रहा था यह देखने के लिए कि क्या मैं आवंटित सभी मेमोरी को रिलीज़ करता हूं या नहीं। इन उपकरणों का उत्पादन अच्छा लग रहा है और ऐसा लगता है कि मैं स्मृति खोना नहीं कर रहा हूं। हालांकि, जब मैं top पर देख रहा हूं और ps का आउटपुट मैं उलझन में हूं क्योंकि यह मूल रूप से प्रतिनिधित्व नहीं करता है जो मैं valgrind और gperftools के साथ देख रहा हूं।सी ++ में मेमोरी उपयोग ट्रैक करें और मेमोरी खपत का मूल्यांकन करें

  • शीर्ष रिपोर्ट:: आरईएस 150M
  • वेलग्रिंड (मासिफ) रिपोर्ट: 23M व्यस्त उपयोग
  • gperftools ढेर प्रोफाइलर रिपोर्ट:

    यहाँ नंबर दिए गए हैं 22.7M व्यस्त उपयोग

मेरा प्रश्न अब है, टी कहां है वह अंतर से आया है? मैंने वालग्रिंड में स्टैक उपयोग को ट्रैक करने के लिए भी कोशिश की लेकिन बिना किसी सफलता के।

कुछ और जानकारी:

  • प्रक्रिया मूल रूप से एक में स्मृति भंडारण
  • एक रिसाव की जांच प्रदर्शन और कुछ ही समय बाद लोड हो रहा है किया जाता है को तोड़ने के लिए सी एपीआई के माध्यम से mysql से डेटा लोड हो रहा है, से पता चलता है एक निश्चित 144 बाइट्स के खो दिया है, और 10M पहुंचा जा सकता है, जो, राशि है कि वर्तमान में आवंटित किया जाता है
  • पुस्तकालय कोई जटिल आईपीसी करता है फिट बैठता है यह कुछ धागे शुरू होता है, लेकिन सूत्र का केवल एक ही काम
  • यह लोड नहीं करता है निष्पादित हो रहा है अन्य जटिल प्रणाली पुस्तकालय एँ
  • पीएसएस आकार से/proc/पीआईडी ​​/ smaps टॉप में आरईएस आकार और ps

से मेल खाती है, तो आप किसी भी विचार है, जहां सूचना स्मृति की खपत में इस अंतर से आता है? मैं कैसे सत्यापित कर सकता हूं कि मेरा प्रोग्राम सही तरीके से व्यवहार कर रहा है? क्या आपके पास कोई विचार है कि मैं इस मुद्दे की और जांच कैसे कर सकता हूं?

+1

क्या अंतर खुद के कारण हो सकता है? –

+1

मैंने Valgrind या gperftools नहीं चलाते समय RES और PSS आकार एकत्र किए, तो नहीं। – grundprinzip

+1

'RES - निवासी आकार (केबी) गैर-स्वैच्छिक भौतिक स्मृति एक कार्य का उपयोग किया गया है। 'मुझे लगता है कि मूर्ख सवाल है, लेकिन मुफ्त() हमेशा आरईएस को कम करता है? एक और लड़के के पास भी इसी तरह के मुद्दे हैं जो मुझे लगता है, http://stackoverflow.com/questions/12262146/free-can-not-release-the-mem-and-decrease-the-value-of-res-column-of- शीर्ष –

उत्तर

14

अंततः मैं समस्या को हल करने में सक्षम था और खुशी से अपने निष्कर्ष साझा करूंगा। आम तौर पर मेरे परिप्रेक्ष्य से एक कार्यक्रम की स्मृति खपत का मूल्यांकन करने के लिए सबसे अच्छा उपकरण Valgrind से Massif उपकरण है। यह आपको ढेर खपत को प्रोफाइल करने की अनुमति देता है और आपको एक विस्तृत विश्लेषण देता है।

अब आपके आवेदन के ढेर को valgrind --tool=massif prog चलाने के लिए प्रोफाइल करने के लिए, यह आपको malloc और दोस्तों जैसे सामान्य स्मृति आवंटन कार्यों के बारे में सभी जानकारी तक मूल पहुंच प्रदान करेगा। हालांकि, गहराई से खोदने के लिए मैंने --pages-as-heap=yes विकल्प को सक्रिय किया जो तब अंडरलेइंग सिस्टम कॉल के बारे में जानकारी भी रिपोर्ट करेगा। एक उदाहरण दिया करने के लिए यहाँ मेरी रूपरेखा सत्र से कुछ है:

67 1,284,382,720  978,575,360  978,575,360    0   0 
100.00% (978,575,360B) (page allocation syscalls) mmap/mremap/brk, --alloc-fns, etc. 
->87.28% (854,118,400B) 0x8282419: mmap (syscall-template.S:82) 
| ->84.80% (829,849,600B) 0x821DF7D: _int_malloc (malloc.c:3226) 
| | ->84.36% (825,507,840B) 0x821E49F: _int_memalign (malloc.c:5492) 
| | | ->84.36% (825,507,840B) 0x8220591: memalign (malloc.c:3880) 
| | | ->84.36% (825,507,840B) 0x82217A7: posix_memalign (malloc.c:6315) 
| | |  ->83.37% (815,792,128B) 0x4C74F9B: std::_Rb_tree_node<std::pair<std::string const, unsigned int> >* std::_Rb_tree<std::string, std::pair<std::string const, unsigned int>, std::_Select1st<std::pair<std::string const, unsigned int> >, std::less<std::string>, StrategizedAllocator<std::pair<std::string const, unsigned int>, MemalignStrategy<4096> > >::_M_create_node<std::pair<std::string, unsigned int> >(std::pair<std::string, unsigned int>&&) (MemalignStrategy.h:13) 
| | |  | ->83.37% (815,792,128B) 0x4C7529F: OrderIndifferentDictionary<std::string, MemalignStrategy<4096>, StrategizedAllocator>::addValue(std::string) (stl_tree.h:961) 
| | |  | ->83.37% (815,792,128B) 0x5458DC9: var_to_string(char***, unsigned long, unsigned long, AbstractTable*) (AbstractTable.h:341) 
| | |  |  ->83.37% (815,792,128B) 0x545A466: MySQLInput::load(std::shared_ptr<AbstractTable>, std::vector<std::vector<ColumnMetadata*, std::allocator<ColumnMetadata*> >*, std::allocator<std::vector<ColumnMetadata*, std::allocator<ColumnMetadata*> >*> > const*, Loader::params const&) (MySQLLoader.cpp:161) 
| | |  |  ->83.37% (815,792,128B) 0x54628F2: Loader::load(Loader::params const&) (Loader.cpp:133) 
| | |  |   ->83.37% (815,792,128B) 0x4F6B487: MySQLTableLoad::executePlanOperation() (MySQLTableLoad.cpp:60) 
| | |  |   ->83.37% (815,792,128B) 0x4F8F8F1: _PlanOperation::execute_throws() (PlanOperation.cpp:221) 
| | |  |    ->83.37% (815,792,128B) 0x4F92B08: _PlanOperation::execute() (PlanOperation.cpp:262) 
| | |  |    ->83.37% (815,792,128B) 0x4F92F00: _PlanOperation::operator()() (PlanOperation.cpp:204) 
| | |  |     ->83.37% (815,792,128B) 0x656F9B0: TaskQueue::executeTask() (TaskQueue.cpp:88) 
| | |  |     ->83.37% (815,792,128B) 0x7A70AD6: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16) 
| | |  |      ->83.37% (815,792,128B) 0x6BAEEFA: start_thread (pthread_create.c:304) 
| | |  |      ->83.37% (815,792,128B) 0x8285F4B: clone (clone.S:112) 
| | |  |       
| | |  ->00.99% (9,715,712B) in 1+ places, all below ms_print's threshold (01.00%) 
| | |  
| | ->00.44% (4,341,760B) in 1+ places, all below ms_print's threshold (01.00%) 

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

इस समस्या को हल करने के लिए, मैं एक छोटे सीमा पर स्विच किया है और इस तरह काफी स्मृति भूमि के ऊपर कम कर सकता है।

मैसिफ़ & कंपनी के सामने मेरे घंटों के समापन के रूप में मैं केवल गहरी प्रोफाइलिंग के लिए इस टूल का उपयोग करने की अनुशंसा कर सकता हूं क्योंकि यह आपको क्या हो रहा है की बहुत अच्छी समझ देता है और आसानी से ट्रैकिंग त्रुटियों की अनुमति देता है। posix_memalign के उपयोग के लिए स्थिति अलग है। ऐसे मामले हैं जहां यह वास्तव में जरूरी है, हालांकि, ज्यादातर मामलों के लिए आप सामान्य malloc के साथ ठीक होंगे।

0

डिफ़ॉल्ट रूप से, मैसिफ़ केवल ढेर आकार की रिपोर्ट करता है। मेमोरी में वास्तविक आकार की शीर्ष रिपोर्ट, प्रोग्राम कोड द्वारा उपयोग किए गए आकार के साथ-साथ स्टैक आकार सहित आकार भी शामिल है।

--stacks=yes विकल्प के साथ मैसिफ़ की आपूर्ति करने का प्रयास करें, यह कुल स्मृति उपयोग की रिपोर्ट करने के लिए कहें, जिसमें स्टैक स्पेस शामिल है और देखें कि क्या यह तस्वीर बदलती है?

+0

मैंने ऊपर बताए अनुसार मैसिफ़ और स्टैक आकार के साथ जांच की, लेकिन ढेर का आकार लगभग 15k के आसपास स्थिर है। – grundprinzip

1

this लेख ps/शीर्ष रिपोर्ट के मुताबिक यदि आपका प्रोग्राम चल रहा है तो यह प्रोग्राम कितनी मेमोरी का उपयोग करता है। मान लें कि आपका प्रोग्राम उदा। एसटीएल जैसे साझा पुस्तकालयों का एक समूह का उपयोग करता है जो पहले ही स्मृति में लोड हो चुके हैं, आपके प्रोग्राम के निष्पादन के कारण आवंटित वास्तविक स्मृति की मात्रा के बीच एक अंतर है, यह एकमात्र प्रक्रिया होने पर कितनी मेमोरी आवंटित की जाएगी।

+0

लेख वह है जहां मुझे पीएसएस आकार के बारे में टिप मिली, इसलिए मैंने इसे चेक किया। आगे की जांच के साथ, अब मैं एक बिंदु पर हूं जहां मेमोरी खपत में कुछ अंतर अंडरलेइंग मॉलोक() कार्यान्वयन से आता है जो बड़े ब्लॉक और कुछ अजीबता को 'const char *' में 'std :: string' रूपांतरणों में आवंटित करेगा । Valpinds massif '--pages-as-heap = yes' विकल्प के साथ बहुत मदद मिली है। – grundprinzip

+0

मैं देखता हूं। आगे की जांच के लिए सिर्फ एक विचार: आपके प्रोग्राम के भीतर आवंटित स्मृति की मात्रा बढ़ाएं (उदा। 24 एमबी -> 512 एमबी -> 1024 एमबी) और देखें कि शीर्ष/पीएस आउटपुट में अपरिभाषित अंतर निरंतर बना रहता है या बढ़ता है। – Christian

संबंधित मुद्दे