2016-07-20 10 views
8

हालांकि यह अन्य प्रश्नों से डुप्लिकेट जैसा दिख सकता है, मुझे बताएं कि यह क्यों नहीं है।लिनक्स (और ओएसएक्स) पर आवंटित स्मृति की मात्रा कैसे पूछें?

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

इस कारण से, मैंने अपने आवेदन द्वारा आवंटित स्मृति की मात्रा के आधार पर एक मानदंड चुना है, यानी वर्चुअल मेमोरी आकार के बहुत करीब है।

यह प्रश्न (How to determine CPU and memory consumption from inside a process?) वर्तमान प्रक्रिया द्वारा उपयोग की जाने वाली वर्चुअल मेमोरी की मात्रा पूछने के महान तरीके प्रदान करता है, जो मुझे लगता था कि मुझे क्या चाहिए था।

विंडोज़ पर, मैं GetProcessMemoryInfo() और PrivateUsage फ़ील्ड का उपयोग कर रहा हूं, जो बहुत अच्छा काम करता है।

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

ओएसएक्स पर, task_info() और virtual_size फ़ील्ड का उपयोग करके, मुझे अपेक्षित संख्या (एक ऐप के लिए कुछ जीबी जो विंडोज़ पर 1 जीबी तक नहीं लेता) से बड़ा मिलता है, लेकिन लिनक्स जितना बड़ा नहीं होता है।

तो यहां बड़ा सवाल है: मैं अपने आवेदन द्वारा आवंटित स्मृति की मात्रा कैसे प्राप्त कर सकता हूं? मुझे पता है कि यह कुछ हद तक एक अस्पष्ट प्रश्न (क्या करता है "आबंटित स्मृति" का अर्थ है?) है, लेकिन मैं लचीला कर रहा हूँ:

  • मैं आवेदन स्थिर डेटा, कोड अनुभाग और सब कुछ शामिल करने के लिए पसंद करते हैं, लेकिन मैं यह कर सकते हैं बिना जीना।
  • मैं ढेर के लिए आवंटित स्मृति को शामिल करना पसंद करूंगा, लेकिन मैं बिना रह सकता हूं।
  • मैं साझा पुस्तकालयों द्वारा उपयोग की गई स्मृति को शामिल करना पसंद करूंगा, लेकिन मैं बिना रह सकता हूं।
  • मुझे वास्तव में mmap सामान की परवाह नहीं है, मैं उस बिंदु के साथ या उसके बिना कर सकता हूं।
  • आदि

क्या वास्तव में महत्वपूर्ण है कि नंबर गतिशील आवंटन (नया, malloc, कुछ भी) के साथ बढ़ता है और जब स्मृति जारी की है सिकुड़ता है (मैं कार्यान्वयन पर निर्भर हो सकता है जो) है।

चीजें मैं

की कोशिश की है यहाँ समाधान के एक जोड़े मैं कोशिश की है और/या के बारे में सोचा है, लेकिन है कि मेरे लिए काम नहीं करेगा।

  1. से पढ़ें/proc/self/स्थिति

    यह दृष्टिकोण कैसे करने के लिए निर्धारित-cpu और स्मृति खपत-से-अंदर-ए-प्रक्रिया द्वारा सुझाए गए है। हालांकि, ऊपर बताए अनुसार, यह वर्चुअल मेमोरी की मात्रा देता है, जो मेरे लिए काम नहीं करता है।

  2. पढ़ें/proc/self/statm से

    बहुत थोड़ा सबसे खराब: http://kernelnewbies.kernelnewbies.narkive.com/iG9xCmwB/proc-pid-statm-doesnt-match-with-status, जो लिनक्स कर्नेल कोड को संदर्भित करता है के अनुसार, उन दो मानों के बीच फर्क सिर्फ इतना है कि एक दूसरे के नहीं है आभासी स्मृति की मात्रा के लिए reserved_vm घटाएं। मुझे लगता है कि reserved_vm में OpenCL ड्राइवर द्वारा आरक्षित स्मृति शामिल होगी, लेकिन ऐसा नहीं है।

  3. उपयोग mallinfo() और uordblks क्षेत्र

    यह सब आवंटन शामिल करने के लिए नहीं लगता है (मैं new रों याद कर रहे हैं अनुमान लगा रहा हूँ), आभासी स्मृति अंतरिक्ष में एक + 2Gb विकास के लिए के बाद से (के बाद कुछ स्मृति-भारी काम कर रहे हैं और अभी भी स्मृति धारण कर रहे हैं), मैं केवल mallinfo() द्वारा लौटाई गई संख्या में 0.1 जीबी वृद्धि देख रहा हूं।

  4. पढ़ें/proc/self से [ढेर] अनुभाग आकार/smaps

    यह मान Kb चारों ओर 336,760 पर शुरू कर दिया और काम है कि + 2Gb से आभासी स्मृति अंतरिक्ष बढ़ी के लिए 1,019,496 Kb पर पहुंचा, और उसके बाद यह कभी नहीं नीचे हो जाता है, तो मुझे यकीन है कि मैं वास्तव में इस नंबर पर भरोसा नहीं कर सकते नहीं कर रहा हूँ ...

  5. मॉनिटर अपने आवेदन में सभी स्मृति आवंटन

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

  6. से पहले और OpenCL संदर्भ प्रारंभ

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

तो मुझे यह सब कुछ मिला है। एक और चीज है जिसे मैंने अभी तक कोशिश नहीं की है, क्योंकि यह केवल ओएसएक्स पर काम करता है, लेकिन Why does mstats and malloc_zone_statistics not show recovered memory after free? में वर्णित दृष्टिकोण का उपयोग करना है, यानी malloc_get_all_zones() और malloc_zone_statistics() का उपयोग करें, लेकिन मुझे लगता है कि यह mallinfo() जैसा ही समस्या हो सकती है, यानी नहीं खाते में सभी आवंटन।

तो, क्या कोई भी लिनक्स में दी गई प्रक्रिया (जैसे ओएसएक्स भी एक अलग विधि है) के मेमोरी उपयोग (जैसा कि एक शब्द की अस्पष्टता है, सटीकता के लिए ऊपर देखें) पूछने का तरीका सुझा सकता है?

+0

mallinfo() के साथ (Arena + hblkhd + uordblks) –

+0

@brianbeuning: http://man7.org/linux/man-pages/man3/mallinfo.3.html के अनुसार, 'Arena' 'uordblks' + है 'fordblks', तो आपका सुझाव कुछ स्मृति को दो बार गिनने का अंत होगा ... –

उत्तर

0

यहाँ मैं का उपयोग कर समाप्त हो गया है। मैं स्कैन/proc/self/नक्शे और सभी पते के आकार योग मेरी मापदंड है, जो बैठक सीमाओं:

  • केवल inode 0 से लेकर शामिल हैं (यानी कोई उपकरण नहीं है, कोई मैप की गई फ़ाइल, आदि)
  • केवल पर्वतमाला हैं कि कम से कम एक, पठनीय लिखने योग्य या निष्पादन
  • केवल मेरे प्रयोगों में निजी स्मृति
    • शामिल मैं inode 0. शायद अंतर-प्रक्रिया साझा स्मृति के साथ से साझा स्मृति के उदाहरण नहीं देखा शामिल हैं। ..?

यहाँ मेरी समाधान के लिए कोड है:

size_t getValue() 
{ 
    FILE* file = fopen("/proc/self/maps", "r"); 
    if (!file) 
    { 
     assert(0); 
     return 0; 
    } 

    size_t value = 0; 

    char line[1024]; 
    while (fgets(line, 1024, file) != NULL) 
    { 
     ptrdiff_t start_address, end_address; 
     char perms[4]; 
     ptrdiff_t offset; 
     int dev_major, dev_minor; 
     unsigned long int inode; 
     const int nb_scanned = sscanf(
      line, "%16tx-%16tx %c%c%c%c %16tx %02x:%02x %lu", 
      &start_address, &end_address, 
      &perms[0], &perms[1], &perms[2], &perms[3], 
      &offset, &dev_major, &dev_minor, &inode 
      ); 
     if (10 != nb_scanned) 
     { 
      assert(0); 
      continue; 
     } 

     if ((inode == 0) && 
      (perms[0] != '-' || perms[1] != '-' || perms[2] != '-') && 
      (perms[3] == 'p')) 
     { 
      assert(dev_major == 0); 
      assert(dev_minor == 0); 
      value += (end_address - start_address); 
     } 
    } 

    fclose(file); 

    return value; 
} 

इस/proc/self/नक्शे में सभी लाइनों के माध्यम से पाशन है, स्मृति में जानना चाहते है कि जिस तरह से उपयोग करने की तुलना में काफी धीमी है के बाद से " वर्चुअल मेमोरी वर्तमान में वर्तमान प्रक्रिया द्वारा उपयोग की जाती है "How to determine CPU and memory consumption from inside a process? से।

हालांकि, यह मुझे जो चाहिए वह बहुत करीब है।

1

आप कोशिश कर सकते हैं और प्रयोग getrusage() द्वारा लौटाए जानकारी: स्मृति जानकारी आप उद्देश्य से मेल नहीं खाती

#include <sys/time.h> 
#include <sys/resource.h> 

int getrusage(int who, struct rusage *usage); 

struct rusage { 
    struct timeval ru_utime; /* user CPU time used */ 
    struct timeval ru_stime; /* system CPU time used */ 
    long ru_maxrss;  /* maximum resident set size */ 
    long ru_ixrss;   /* integral shared memory size */ 
    long ru_idrss;   /* integral unshared data size */ 
    long ru_isrss;   /* integral unshared stack size */ 
    long ru_minflt;  /* page reclaims (soft page faults) */ 
    long ru_majflt;  /* page faults (hard page faults) */ 
    long ru_nswap;   /* swaps */ 
    long ru_inblock;  /* block input operations */ 
    long ru_oublock;  /* block output operations */ 
    long ru_msgsnd;  /* IPC messages sent */ 
    long ru_msgrcv;  /* IPC messages received */ 
    long ru_nsignals;  /* signals received */ 
    long ru_nvcsw;   /* voluntary context switches */ 
    long ru_nivcsw;  /* involuntary context switches */ 
}; 

हैं, अवलोकन पृष्ठ दोष मायने रखता है जो आप का पता लगाने का इरादा मॉनिटर स्मृति तनाव, कर सकते हैं।

+0

सुझाव के लिए धन्यवाद। मैंने कोशिश की ('ru_ixrss',' ru_idrss' और 'ru_isrss' पढ़ना) और सभी फ़ील्ड में 0 है।मैन पेज के मुताबिक, "सभी फ़ील्ड पूरा नहीं हुए हैं; अनियमित फ़ील्ड कर्नेल द्वारा शून्य पर सेट हैं।" और "लिनक्स 2.4 में केवल फ़ील्ड ru_utime, ru_stime, ru_minflt, और ru_majflt बनाए रखा जाता है। चूंकि लिनक्स 2.6, ru_nvcsw और ru_nivcsw भी बनाए रखा जाता है।" –

1

क्या आपने ऊपर सेक्शन (5) के लिए लिनक्स के लिए साझा लाइब्रेरी इंटरपोजर की कोशिश की है? जब तक आपका एप्लिकेशन मॉलोक फ़ंक्शंस को स्थिर रूप से लिंक नहीं कर रहा है, तब तक आप अपने प्रोग्राम और कर्नेल मॉलोक के बीच एक नया फ़ंक्शन इंटरैक्ट कर सकते हैं। मैंने मेमोरी उपयोग पर आंकड़े एकत्र करने के लिए कई बार इस रणनीति का उपयोग किया है।

प्रोग्राम चलाने से पहले इसे एलडी_PRELOAD सेटिंग की आवश्यकता है लेकिन कोई स्रोत या बाइनरी परिवर्तन नहीं है। यह कई मामलों में एक आदर्श जवाब है।

http://www.drdobbs.com/building-library-interposers-for-fun-and/184404926

आप शायद भी calloc और क्या करना चाहते हैं जाएगा:

यहाँ एक malloc interposer का एक उदाहरण है। आम तौर पर कॉल करने के लिए कॉल के रूप में नए कॉल करने के लिए कॉल C++ भी शामिल है।

ओएस एक्स की समान क्षमताएं प्रतीत होती हैं लेकिन मैंने कोशिश नहीं की है।

http://tlrobinson.net/blog/2007/12/overriding-library-functions-in-mac-os-x-the-easy-way-dyld_insert_libraries/

--Matt

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