web-dev-qa-db-fra.com

Comment utiliser la mémoire au moment de l'exécution en utilisant C++?

Je dois obtenir les informations d'utilisation VIRT et RES au moment de l'exécution de mon programme et les afficher.

Ce que j'ai essayé jusqu'à présent:

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;

mais je reçois toujours 0.

74
frenk

Sous Linux, je n'ai jamais trouvé de solution ioctl () . Pour nos applications, nous avons codé une routine d’utilité générale basée sur la lecture de fichiers dans/proc/pid . Un certain nombre de ces fichiers donnent des résultats différents. Voici celle sur laquelle nous nous sommes penchés (la question portait la mention C++ et nous avons géré les E/S à l'aide de constructions C++, mais elle devrait être facilement adaptable aux routines C/S si vous en avez besoin):

#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 a mis une bonne fonction autonome C pour obtenir la taille définie du processus (utilisation de la mémoire physique) sur son site web:

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

Usage

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

Pour plus de discussion, consultez le site Web, il fournit également une fonction permettant d’obtenir la taille de la mémoire physique d’un système .

43
pepper_chico

Vieux:

maxrss indique le maximum disponible mémoire pour le processus. 0 signifie que aucune limite n'est imposée au processus. Quoi vous voulez probablement des données non partagées utilisation ru_idrss.

Nouveau: Il semble que ce qui précède ne fonctionne pas, car le noyau ne remplit pas la plupart des valeurs. Ce qui marche, c’est d’obtenir les informations de proc. Au lieu de l’analyser soi-même, il est plus facile d’utiliser libproc (une partie de procps) comme suit:

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

Compiler avec "gcc -o getrusage getrusage.c -lproc"

19
Paul de Vrieze

Sur linux, si vous pouvez vous permettre le coût en temps d'exécution (pour le débogage), vous pouvez utiliser valgrind avec l'outil massif:

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

C'est lourd, mais très utile.

9
David Cournapeau

Les réponses existantes indiquent mieux comment obtenir la valeur correcte, mais je peux au moins expliquer pourquoi getrusage ne fonctionne pas pour vous.

homme 2 getrusage:

La structure ci-dessus a été extraite de BSD 4.3 Reno. Tous les champs ne sont pas significatifs sous Linux. Actuellement (Linux 2.4, 2.6), seuls les champs ru_utime, ru_stime, ru_minflt, ru_majflt et ru_nswap sont conservés.

6
jmanning2k

Un moyen plus élégant pour la méthode Don Wakefield:

#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

en plus de votre chemin
vous pouvez appeler la commande système ps et obtenir l’utilisation de la mémoire de la sortie.
ou lire les informations de/proc/pid (voir la structure PIOCPSINFO)

3
bayda

Basé sur la solution de Don W, avec moins de variables.

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

J'utilise une autre méthode pour le faire et cela semble réaliste. Ce que je fais, c'est que j'ai le PID du processus par la fonction getpid () puis j'utilise le fichier/proc/pid/stat. Je crois que la 23ème colonne du fichier de statistiques est le vmsize (regardez le post de Don). Vous pouvez lire vmsize à partir du fichier à tout moment dans le code. Si vous vous demandez combien de code peut utiliser de la mémoire, vous pouvez lire ce fichier une fois avant et une fois après et vous pouvez les soustraire les uns aux autres.

1
Amir

Je cherchais une application Linux pour mesurer le maximum de mémoire utilisée. Valgrind est un excellent outil, mais me donnait plus d'informations que je ne le souhaitais. tstime semblait être le meilleur outil que j'ai pu trouver. Il mesure l'utilisation de la mémoire "highwater" (RSS et virtuelle). Voir cette réponse .

0
jtpereyda