C ++ का उपयोग करके रनटाइम पर मेमोरी उपयोग कैसे प्राप्त करें?


90

मुझे अपने कार्यक्रम के चलाने के समय मेम का उपयोग VIRT और RES प्राप्त करना होगा और उन्हें प्रदर्शित करना होगा।

मैंने अब तक क्या कोशिश की:

getrusage ( http://linux.die.net/man/2/getrusage )

int who = RUSAGE_SELF; 
struct rusage usage; 
int ret; 

ret=getrusage(who,&usage);

cout<<usage.ru_maxrss;

लेकिन मुझे हमेशा 0 मिलता है।


3
यह सिस्टम आश्रित है - ऐसा लगता है कि आपका सिस्टम गेटअर्स के माध्यम से रिपोर्टिंग अधिकतम का समर्थन नहीं करता है - क्या आप हमें बता सकते हैं कि आप किस वितरण का उपयोग कर रहे हैं?
tvanfosson

जवाबों:


79

लिनक्स पर, मैंने कभी ioctl () समाधान नहीं पाया है । हमारे अनुप्रयोगों के लिए, हमने / proc / pid में फ़ाइलों को पढ़ने के आधार पर एक सामान्य उपयोगिता दिनचर्या को कोडित किया । इन फ़ाइलों की एक संख्या है जो अलग-अलग परिणाम देती है। यहाँ हम जिस पर बसे हैं (प्रश्न C ++ को टैग किया गया था, और हमने C ++ कंस्ट्रक्शन का उपयोग करके I / O को संभाला था, लेकिन अगर आपको इसकी आवश्यकता है तो यह आसानी से C i / o रूटीन के अनुकूल होना चाहिए:

#include <unistd.h>
#include <ios>
#include <iostream>
#include <fstream>
#include <string>

//////////////////////////////////////////////////////////////////////////////
//
// process_mem_usage(double &, double &) - takes two doubles by reference,
// attempts to read the system-dependent data for a process' virtual memory
// size and resident set size, and return the results in KB.
//
// On failure, returns 0.0, 0.0

void process_mem_usage(double& vm_usage, double& resident_set)
{
   using std::ios_base;
   using std::ifstream;
   using std::string;

   vm_usage     = 0.0;
   resident_set = 0.0;

   // 'file' stat seems to give the most reliable results
   //
   ifstream stat_stream("/proc/self/stat",ios_base::in);

   // dummy vars for leading entries in stat that we don't care about
   //
   string pid, comm, state, ppid, pgrp, session, tty_nr;
   string tpgid, flags, minflt, cminflt, majflt, cmajflt;
   string utime, stime, cutime, cstime, priority, nice;
   string O, itrealvalue, starttime;

   // the two fields we want
   //
   unsigned long vsize;
   long rss;

   stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr
               >> tpgid >> flags >> minflt >> cminflt >> majflt >> cmajflt
               >> utime >> stime >> cutime >> cstime >> priority >> nice
               >> O >> itrealvalue >> starttime >> vsize >> rss; // don't care about the rest

   stat_stream.close();

   long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages
   vm_usage     = vsize / 1024.0;
   resident_set = rss * page_size_kb;
}

int main()
{
   using std::cout;
   using std::endl;

   double vm, rss;
   process_mem_usage(vm, rss);
   cout << "VM: " << vm << "; RSS: " << rss << endl;
}

क्या आपके पास अलग-अलग * निक्स प्लेटफार्मों के तहत / proc / self / स्टेट स्ट्रक्चर के बारे में कोई गारंटी है? ... मुझे यकीन नहीं है, लेकिन अगर हाँ - यह अच्छा होगा।
बियाडा

खैर, वर्षों से मैंने ज्यादातर सोलारिस, एचपी-यूएक्स और लिनक्स का उपयोग किया है। / proc / self / stat एक Linux-ism लगता है। ऊपर दिए गए प्रोग्राम के मूल संस्करण में भिन्न होने के बाद से सोलारिस के लिए #if ब्लॉक थे।
डॉन वेकफील्ड

मैं यह मान रहा हूं कि ओपी केवल प्रश्न टैगिंग के आधार पर लिनक्स के बारे में परवाह करता है। पढना / पाना आपके लिए जितना अच्छा होगा उतना ही अच्छा होगा। सोलारिस पर आप केस्टैट के माध्यम से सभी प्रकार के सामानों की जानकारी प्राप्त कर सकते हैं (हालांकि यह अक्सर दोहराता है कि आप हर साधन के माध्यम से क्या प्राप्त कर सकते हैं)।
stsquad

मुझे पार्टी में केवल 10 साल देर हो चुकी है, लेकिन क्या आप मुझे बताएंगे कि आप 1024 के बजाय 1024.0 तक बनाम विभाजन क्यों करते हैं?
a_river_in_canada

1
पुनः: why 1024.0?- यह कंपाइलर को डबल FIRST में बदलने के लिए कहता है और फिर डबल परिणाम प्राप्त करने के लिए डिवाइड करता है। अन्य विकल्प: vm_usage = vsize / 1024;पहले विभाजित करना होगा, (@DonWakefield के रूप में सटीकता खोना) और फिर डबल में परिवर्तित होना।
जेसी चिशोल्म

52

डेविड रॉबर्ट नडेऊ ने अपनी वेबसाइट में प्रक्रिया के निवासी आकार (भौतिक मेमोरी का उपयोग) को प्राप्त करने के लिए एक अच्छा स्व - निहित बहु-मंच सी फ़ंक्शन रखा है:

/*
 * Author:  David Robert Nadeau
 * Site:    http://NadeauSoftware.com/
 * License: Creative Commons Attribution 3.0 Unported License
 *          http://creativecommons.org/licenses/by/3.0/deed.en_US
 */

#if defined(_WIN32)
#include <windows.h>
#include <psapi.h>

#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
#include <unistd.h>
#include <sys/resource.h>

#if defined(__APPLE__) && defined(__MACH__)
#include <mach/mach.h>

#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
#include <fcntl.h>
#include <procfs.h>

#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
#include <stdio.h>

#endif

#else
#error "Cannot define getPeakRSS( ) or getCurrentRSS( ) for an unknown OS."
#endif





/**
 * Returns the peak (maximum so far) resident set size (physical
 * memory use) measured in bytes, or zero if the value cannot be
 * determined on this OS.
 */
size_t getPeakRSS( )
{
#if defined(_WIN32)
    /* Windows -------------------------------------------------- */
    PROCESS_MEMORY_COUNTERS info;
    GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
    return (size_t)info.PeakWorkingSetSize;

#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
    /* AIX and Solaris ------------------------------------------ */
    struct psinfo psinfo;
    int fd = -1;
    if ( (fd = open( "/proc/self/psinfo", O_RDONLY )) == -1 )
        return (size_t)0L;      /* Can't open? */
    if ( read( fd, &psinfo, sizeof(psinfo) ) != sizeof(psinfo) )
    {
        close( fd );
        return (size_t)0L;      /* Can't read? */
    }
    close( fd );
    return (size_t)(psinfo.pr_rssize * 1024L);

#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
    /* BSD, Linux, and OSX -------------------------------------- */
    struct rusage rusage;
    getrusage( RUSAGE_SELF, &rusage );
#if defined(__APPLE__) && defined(__MACH__)
    return (size_t)rusage.ru_maxrss;
#else
    return (size_t)(rusage.ru_maxrss * 1024L);
#endif

#else
    /* Unknown OS ----------------------------------------------- */
    return (size_t)0L;          /* Unsupported. */
#endif
}





/**
 * Returns the current resident set size (physical memory use) measured
 * in bytes, or zero if the value cannot be determined on this OS.
 */
size_t getCurrentRSS( )
{
#if defined(_WIN32)
    /* Windows -------------------------------------------------- */
    PROCESS_MEMORY_COUNTERS info;
    GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
    return (size_t)info.WorkingSetSize;

#elif defined(__APPLE__) && defined(__MACH__)
    /* OSX ------------------------------------------------------ */
    struct mach_task_basic_info info;
    mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
    if ( task_info( mach_task_self( ), MACH_TASK_BASIC_INFO,
        (task_info_t)&info, &infoCount ) != KERN_SUCCESS )
        return (size_t)0L;      /* Can't access? */
    return (size_t)info.resident_size;

#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
    /* Linux ---------------------------------------------------- */
    long rss = 0L;
    FILE* fp = NULL;
    if ( (fp = fopen( "/proc/self/statm", "r" )) == NULL )
        return (size_t)0L;      /* Can't open? */
    if ( fscanf( fp, "%*s%ld", &rss ) != 1 )
    {
        fclose( fp );
        return (size_t)0L;      /* Can't read? */
    }
    fclose( fp );
    return (size_t)rss * (size_t)sysconf( _SC_PAGESIZE);

#else
    /* AIX, BSD, Solaris, and Unknown OS ------------------------ */
    return (size_t)0L;          /* Unsupported. */
#endif
}

प्रयोग

size_t currentSize = getCurrentRSS( );
size_t peakSize    = getPeakRSS( );

अधिक चर्चा के लिए, वेब साइट की जांच करें, यह एक सिस्टम की भौतिक मेमोरी आकार प्राप्त करने के लिए एक फ़ंक्शन भी प्रदान करता है


2
बेहतर गुंजाइश के #pragma comment(lib, "psapi.lib")लिए जोड़ा गया था #if defined(_WIN32)
ब्लडमून

1
@ बाढ़ क्या है अगर कोई विंडोज़ का उपयोग कर रहा है लेकिन Microsoft कंपाइलर नहीं है? यह संकलक संकलक को विफल कर देगा।
एड्रियन

यह कोड rusage :: ru_maxrss getrusage का उपयोग करता है, जिसे ओपी ने उसके लिए काम नहीं करने के रूप में रिपोर्ट किया था।
18

21

पुराना:

maxrss प्रक्रिया के लिए अधिकतम उपलब्ध स्मृति बताता है। 0 का मतलब है कि प्रक्रिया की कोई सीमा नहीं है। आप जो चाहते हैं, वह डेटा का उपयोग नहीं है ru_idrss

नई: ऐसा लगता है कि ऊपर वास्तव में काम नहीं करता है, क्योंकि कर्नेल अधिकांश मानों को नहीं भरता है। क्या काम करता है जानकारी खरीद से प्राप्त करने के लिए है। हालांकि, इसे स्वयं को पार्स करने के बजाय, यह इस प्रकार के रूप में लिबरप्रो (खरीद का हिस्सा) का उपयोग करना आसान है:

// getrusage.c
#include <stdio.h>
#include <proc/readproc.h>

int main() {
  struct proc_t usage;
  look_up_our_self(&usage);
  printf("usage: %lu\n", usage.vsize);
}

" gcc -o getrusage getrusage.c -lproc" के साथ संकलन


1
सिवाय इसके न तो कोई क्षेत्र लिनक्स में उपलब्ध है।
jmanning2k

2
यह गलत है। maxrss प्रक्रिया का चरम मेमोरी उपयोग है, न कि अधिकतम उपलब्ध - जो कि गेटलिमिट (RLIMIT_DATA, & rl) होगा।
jmanning2k

1
#include <proc/readproc.h>समाधान उबंटू के तहत मेरे लिए महान काम किया। मुझे पैकेज स्थापित करना था libproc-devusage.vm_dataएक पर्याप्त पर्याप्त सन्निकटन है जिसकी मुझे आवश्यकता थी। मेमोरी स्टेटिस्टिक की आपकी पसंद को यहां प्रलेखित किया गया है: /usr/include/proc/readproc.hजिन लोगों की मैंने कोशिश की थी वे सभी बाइट्स में प्रतीत होते हैं, न कि पृष्ठों पर। मुझे नहीं लगता कि मेरी प्रक्रिया 46 मिलियन पृष्ठों का उपयोग कर रही थी। टिप्पणियाँ कि यह समाधान लिनक्स के तहत काम नहीं करता है गुमराह लगता है।
एलन स्टोक्स 8

2
सही लिंकर है: -lprocps
18:24 पर सेफ़

महान काम करता है, यह एक स्वीकृत उत्तर होना चाहिए!
पैकोव

9

लिनक्स पर, यदि आप रन टाइम कॉस्ट (डिबगिंग के लिए) खर्च कर सकते हैं, तो आप वेलसइंड का उपयोग मासिफ टूल के साथ कर सकते हैं:

http://valgrind.org/docs/manual/ms-manual.html

यह भारी वजन है, लेकिन बहुत उपयोगी है।


8

डॉन वेकफील्ड विधि के लिए एक और अधिक सुंदर तरीका:

#include <iostream>
#include <fstream>

using namespace std;

int main(){

    int tSize = 0, resident = 0, share = 0;
    ifstream buffer("/proc/self/statm");
    buffer >> tSize >> resident >> share;
    buffer.close();

    long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages
    double rss = resident * page_size_kb;
    cout << "RSS - " << rss << " kB\n";

    double shared_mem = share * page_size_kb;
    cout << "Shared Memory - " << shared_mem << " kB\n";

    cout << "Private Memory - " << rss - shared_mem << "kB\n";
    return 0;
}

7

सही मूल्य कैसे प्राप्त करें, इसके लिए मौजूदा उत्तर बेहतर हैं, लेकिन मैं कम से कम यह बता सकता हूं कि गेटशेज आपके लिए काम क्यों नहीं कर रहा है।

आदमी 2 मिलावट:

उपरोक्त संरचना [rusage] BSD 4.3 रेनो से ली गई थी। सभी क्षेत्र लिनक्स के तहत सार्थक नहीं हैं। अभी (Linux 2.4, 2.6) केवल फ़ील्ड ru_utime, ru_stime, ru_minflt, ru_majflt, और ru_nswap बनाए रखा जाता है।


3

अपने तरीके से अतिरिक्त में
आप सिस्टम पीएस कमांड को कॉल कर सकते हैं और आउटपुट से मेमोरी का उपयोग कर सकते हैं।
या से जानकारी पढ़ें / खरीद / pid (PIOCPSINFO संरचना देखें)


PIOCPSINFO वास्तव में मेरे द्वारा उपयोग किए गए किसी भी लिनक्स पर उपलब्ध नहीं है। / Proc / pid से पढ़ना बहुत आम है। मैं एक उत्तर में लिनक्स के लिए उदाहरण कोड पोस्ट करूंगा ...
डॉन वेकफील्ड

हां / proc / pid स्ट्रक्चर्स couls अलग-अलग * nix प्लेटफॉर्म में अलग-अलग हो सकते हैं, लेकिन अगर आपके पास PIOCPSINFO है तो कोई बात नहीं। मेरे पास ऐसी स्थिति है जब इस संरचना को कुछ सोलारिस संस्करण पर परिभाषित नहीं किया गया था .. मैंने इस मामले में पीएस आउटपुट का उपयोग किया है।
बियाडा

2

आपके सिस्टम पर एक फ़ाइल है जिसका नाम है /proc/self/statm। Proc फाइलसिस्टम एक छद्म-फाइलसिस्टम है जो कर्नेल डेटा संरचनाओं को एक इंटरफ़ेस प्रदान करता है। इस फ़ाइल में वे जानकारी हैं जो आपको केवल पूर्णांकों के साथ स्तंभों में चाहिए जो अंतरिक्ष अलग हैं।

कॉलम नं .:

  1. = कुल कार्यक्रम का आकार (VmSize in / proc / [pid] / स्थिति)

  2. = निवासी सेट आकार (VmRSS / proc / [pid] / स्थिति)

अधिक जानकारी के लिए लिंक देखें ।


1

मैं ऐसा करने के लिए अन्य तरीके का उपयोग कर रहा हूं और यह यथार्थवादी लगता है। मैं क्या कर रहा हूँ मुझे getpid () फ़ंक्शन द्वारा प्रक्रिया का PID मिला है और फिर मैं / proc / pid / stat फ़ाइल का उपयोग करता हूं। मेरा मानना ​​है कि स्टेट फाइल का 23 वाँ कॉलम vmsize (डॉन पोस्ट को देखो) है। जहाँ भी आपको कोड की आवश्यकता हो, आप फ़ाइल से vmsize पढ़ सकते हैं। यदि आप आश्चर्य करते हैं कि किसी कोड का स्निपेट मेमोरी का कितना उपयोग कर सकता है, तो आप उस स्निपेट से पहले एक बार उस फ़ाइल को पढ़ सकते हैं और एक बार के बाद और आप उन्हें एक दूसरे से घटा सकते हैं।


1

कम चर के साथ डॉन डब्ल्यू के समाधान पर आधारित है।

void process_mem_usage(double& vm_usage, double& resident_set)
{
    vm_usage     = 0.0;
    resident_set = 0.0;

    // the two fields we want
    unsigned long vsize;
    long rss;
    {
        std::string ignore;
        std::ifstream ifs("/proc/self/stat", std::ios_base::in);
        ifs >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore
                >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore
                >> ignore >> ignore >> vsize >> rss;
    }

    long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages
    vm_usage = vsize / 1024.0;
    resident_set = rss * page_size_kb;
}

0

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.