wake-up-neo.net

Wie bekomme ich zur Laufzeit mit C++ Speicherauslastung?

Ich muss zur Laufzeit meines Programms die Speicherbelegung VIRT und RES abrufen und anzeigen.

Was ich bisher ausprobiert habe:

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;

aber ich bekomme immer 0.

74
frenk

Unter Linux habe ich noch keine ioctl () -Lösung gefunden. Für unsere Anwendungen haben wir ein allgemeines Dienstprogramm programmiert, das auf dem Lesen von Dateien in/proc/pid basiert. Es gibt eine Reihe dieser Dateien, die unterschiedliche Ergebnisse liefern. Hier haben wir uns entschieden (die Frage wurde mit C++ gekennzeichnet und wir haben E/A mit C++ - Konstrukten gehandhabt, aber sie sollte sich leicht an C/A-Routinen anpassen lassen, wenn Sie müssen):

#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;
}
68
Don Wakefield

David Robert Nadeau hat eine gute in sich geschlossene Multi-Plattform-C-Funktion zur Verfügung gestellt, um die prozess residente eingestellte Größe (physische Speichernutzung) zu ermitteln

/*
 * 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
}

Verwendungszweck

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

Weitere Informationen finden Sie auf der Website. Sie bietet außerdem eine Funktion zum Abrufen der physischen Speichergröße eines Systems .

43
pepper_chico

Alt:

maxrss gibt den maximal verfügbaren Wert an Speicher für den Prozess. 0 bedeutet, dass Dem Prozess sind keine Grenzen gesetzt. Was Sie möchten wahrscheinlich ungeteilte Daten Verwendung ru_idrss.

Neu: Das Obige scheint nicht wirklich zu funktionieren, da der Kernel die meisten Werte nicht ausfüllt. Was funktioniert, ist, die Informationen von proc zu erhalten. Statt es selbst zu analysieren, ist es jedoch einfacher, libproc (Teil von procps) wie folgt zu verwenden:

// 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);
}

Kompilieren Sie mit "gcc -o getrusage getrusage.c -lproc"

19
Paul de Vrieze

Wenn Sie unter Linux die Laufzeitkosten (für das Debugging) leisten können, können Sie valgrind mit dem Massiv-Tool verwenden:

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

Es ist schwer, aber sehr nützlich.

9

Die vorhandenen Antworten sind besser, um den richtigen Wert zu erhalten, aber ich kann zumindest erklären, warum getrusage für Sie nicht funktioniert.

mann 2 getrusage:

Die obige Struktur wurde von BSD 4.3 Reno übernommen. Nicht alle Felder sind unter Linux von Bedeutung. Derzeit (Linux 2.4, 2.6) werden nur die Felder ru_utime, ru_stime, ru_minflt, ru_majflt und ru_nswap beibehalten.

6
jmanning2k

Eine elegantere Methode für die Don Wakefield-Methode:

#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;
}
4
Qsiris

zusätzlich zu Ihrem Weg
Sie könnten den Befehl system ps aufrufen und die Speicherauslastung von der Ausgabe erhalten.
oder lesen Sie Informationen aus/proc/pid (siehe PIOCPSINFO-Struktur)

3
bayda

Basierend auf der Lösung von Don W. mit weniger Variablen.

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;
}
1

Ich benutze das auf andere Weise und es klingt realistisch. Was ich mache ist, ich habe die PID des Prozesses durch die getpid () - Funktion erhalten und dann benutze ich/proc/pid/stat. Ich glaube, die 23. Spalte der stat-Datei ist vmsize (siehe Don Post). Sie können vmsize aus der Datei lesen, wo immer Sie es benötigen. Wenn Sie sich fragen, wie viel ein Code-Snippet Speicher verwenden kann, können Sie diese Datei einmal vor diesem Snippet und danach lesen und sie voneinander subtrahieren.

1
Amir

Ich suchte nach einer Linux-App, um den maximal verwendeten Speicher zu messen. valgrind ist ein hervorragendes Werkzeug, gab mir jedoch mehr Informationen, als ich wollte. tstime schien das beste Werkzeug zu sein, das ich finden konnte. Es misst die Speichernutzung im Hochwasserbereich (RSS und virtuell). Siehe diese Antwort .

0
jtpereyda