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