774 Stimmen

Wie man den CPU- und Speicherverbrauch innerhalb eines Prozesses ermittelt

Ich hatte einmal die Aufgabe, die folgenden Leistungsparameter innerhalb einer laufenden Anwendung zu ermitteln:

  • Gesamter verfügbarer virtueller Speicher

  • Derzeit genutzter virtueller Speicher

  • Virtueller Speicher, der derzeit von meinem Prozess verwendet wird

  • Verfügbares RAM insgesamt

  • Derzeit genutztes RAM

  • Derzeit von meinem Prozess genutztes RAM

  • % aktuell genutzte CPU

  • % CPU, die derzeit von meinem Prozess verwendet wird

Der Code musste unter Windows und Linux laufen. Obwohl dies eine Standardaufgabe zu sein scheint, hat es mich mehrere Tage gekostet, die notwendigen Informationen in den Handbüchern (WIN32 API, GNU docs) und im Internet zu finden, da es dort so viele unvollständige/unrichtige/veraltete Informationen zu diesem Thema gibt.

Um anderen die gleichen Schwierigkeiten zu ersparen, dachte ich, es wäre eine gute Idee, alle verstreuten Informationen und das, was ich durch Versuch und Irrtum herausgefunden habe, hier an einem Ort zu sammeln.

19 Stimmen

Die Angabe "gesamter verfügbarer virtueller Speicher" ist auf modernen Betriebssystemen bedeutungslos.

82 Stimmen

Warum ist sie bedeutungslos? Macht sie die Antwort hier ungültig? stackoverflow.com/questions/3296211/ ... bitte keine Cliffhanger in den Kommentaren, das ist keine Fernsehserie.

6 Stimmen

@MindaugasBernatavicius: Die verlinkte Frage bezieht sich auf den "gesamten physischen Speicher", der eine dem Betriebssystem bekannte Hardware-Tatsache ist. Man erhält die Summe, indem man die Größen aller Speichermodule addiert. "Verfügbarer virtueller Gesamtspeicher" hingegen, was bedeutet das überhaupt? Ist das der kombinierte virtuelle Adressraum aller Prozesse, die theoretisch erstellt werden könnten? Diese Zahl liegt bei etwa 2^80 Byte und ist damit sicherlich bedeutungslos.

6voto

souch Punkte 121

Mac OS X - CPU

Gesamte CPU-Nutzung:

En Abrufen von Systeminformationen unter Mac OS X :

#include <mach/mach_init.h>
#include <mach/mach_error.h>
#include <mach/mach_host.h>
#include <mach/vm_map.h>

static unsigned long long _previousTotalTicks = 0;
static unsigned long long _previousIdleTicks = 0;

// Returns 1.0f for "CPU fully pinned", 0.0f for "CPU idle", or somewhere in between
// You'll need to call this at regular intervals, since it measures the load between
// the previous call and the current one.
float GetCPULoad()
{
   host_cpu_load_info_data_t cpuinfo;
   mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
   if (host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)&cpuinfo, &count) == KERN_SUCCESS)
   {
      unsigned long long totalTicks = 0;
      for(int i=0; i<CPU_STATE_MAX; i++) totalTicks += cpuinfo.cpu_ticks[i];
      return CalculateCPULoad(cpuinfo.cpu_ticks[CPU_STATE_IDLE], totalTicks);
   }
   else return -1.0f;
}

float CalculateCPULoad(unsigned long long idleTicks, unsigned long long totalTicks)
{
  unsigned long long totalTicksSinceLastTime = totalTicks-_previousTotalTicks;
  unsigned long long idleTicksSinceLastTime  = idleTicks-_previousIdleTicks;
  float ret = 1.0f-((totalTicksSinceLastTime > 0) ? ((float)idleTicksSinceLastTime)/totalTicksSinceLastTime : 0);
  _previousTotalTicks = totalTicks;
  _previousIdleTicks  = idleTicks;
  return ret;
}

5voto

Boernii Punkte 111

QNX

Da dies wie eine "Wikipage des Codes" ist, möchte ich etwas Code aus der QNX Knowledge Base hinzufügen (Anmerkung: dies ist nicht meine Arbeit, aber ich habe es überprüft und es funktioniert gut auf meinem System):

So erhalten Sie die CPU-Auslastung in %: http://www.qnx.com/support/knowledgebase.html?id=50130000000P9b5

#include <atomic.h>
#include <libc.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/iofunc.h>
#include <sys/neutrino.h>
#include <sys/resmgr.h>
#include <sys/syspage.h>
#include <unistd.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/debug.h>
#include <sys/procfs.h>
#include <sys/syspage.h>
#include <sys/neutrino.h>
#include <sys/time.h>
#include <time.h>
#include <fcntl.h>
#include <devctl.h>
#include <errno.h>

#define MAX_CPUS 32

static float Loads[MAX_CPUS];
static _uint64 LastSutime[MAX_CPUS];
static _uint64 LastNsec[MAX_CPUS];
static int ProcFd = -1;
static int NumCpus = 0;

int find_ncpus(void) {
    return NumCpus;
}

int get_cpu(int cpu) {
    int ret;
    ret = (int)Loads[ cpu % MAX_CPUS ];
    ret = max(0,ret);
    ret = min(100,ret);
    return( ret );
}

static _uint64 nanoseconds( void ) {
    _uint64 sec, usec;
    struct timeval tval;
    gettimeofday( &tval, NULL );
    sec = tval.tv_sec;
    usec = tval.tv_usec;
    return( ( ( sec * 1000000 ) + usec ) * 1000 );
}

int sample_cpus( void ) {
    int i;
    debug_thread_t debug_data;
    _uint64 current_nsec, sutime_delta, time_delta;
    memset( &debug_data, 0, sizeof( debug_data ) );

    for( i=0; i<NumCpus; i++ ) {
        /* Get the sutime of the idle thread #i+1 */
        debug_data.tid = i + 1;
        devctl( ProcFd, DCMD_PROC_TIDSTATUS,
        &debug_data, sizeof( debug_data ), NULL );
        /* Get the current time */
        current_nsec = nanoseconds();
        /* Get the deltas between now and the last samples */
        sutime_delta = debug_data.sutime - LastSutime[i];
        time_delta = current_nsec - LastNsec[i];
        /* Figure out the load */
        Loads[i] = 100.0 - ( (float)( sutime_delta * 100 ) / (float)time_delta );
        /* Flat out strange rounding issues. */
        if( Loads[i] < 0 ) {
            Loads[i] = 0;
        }
        /* Keep these for reference in the next cycle */
        LastNsec[i] = current_nsec;
        LastSutime[i] = debug_data.sutime;
    }
    return EOK;
}

int init_cpu( void ) {
    int i;
    debug_thread_t debug_data;
    memset( &debug_data, 0, sizeof( debug_data ) );
/* Open a connection to proc to talk over.*/
    ProcFd = open( "/proc/1/as", O_RDONLY );
    if( ProcFd == -1 ) {
        fprintf( stderr, "pload: Unable to access procnto: %s\n",strerror( errno ) );
        fflush( stderr );
        return -1;
    }
    i = fcntl(ProcFd,F_GETFD);
    if(i != -1){
        i |= FD_CLOEXEC;
        if(fcntl(ProcFd,F_SETFD,i) != -1){
            /* Grab this value */
            NumCpus = _syspage_ptr->num_cpu;
            /* Get a starting point for the comparisons */
            for( i=0; i<NumCpus; i++ ) {
                /*
                * the sutime of idle thread is how much
                * time that thread has been using, we can compare this
                * against how much time has passed to get an idea of the
                * load on the system.
                */
                debug_data.tid = i + 1;
                devctl( ProcFd, DCMD_PROC_TIDSTATUS, &debug_data, sizeof( debug_data ), NULL );
                LastSutime[i] = debug_data.sutime;
                LastNsec[i] = nanoseconds();
            }
            return(EOK);
        }
    }
    close(ProcFd);
    return(-1);
}

void close_cpu(void){
    if(ProcFd != -1){
        close(ProcFd);
        ProcFd = -1;
    }
}

int main(int argc, char* argv[]){
    int i,j;
    init_cpu();
    printf("System has: %d CPUs\n", NumCpus);
    for(i=0; i<20; i++) {
        sample_cpus();
        for(j=0; j<NumCpus;j++)
        printf("CPU #%d: %f\n", j, Loads[j]);
        sleep(1);
    }
    close_cpu();
}

Wie man den kostenlosen (!) Speicher erhält: http://www.qnx.com/support/knowledgebase.html?id=50130000000mlbx

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <err.h>
#include <sys/stat.h>
#include <sys/types.h>

int main( int argc, char *argv[] ){
    struct stat statbuf;
    paddr_t freemem;
    stat( "/proc", &statbuf );
    freemem = (paddr_t)statbuf.st_size;
    printf( "Free memory: %d bytes\n", freemem );
    printf( "Free memory: %d KB\n", freemem / 1024 );
    printf( "Free memory: %d MB\n", freemem / ( 1024 * 1024 ) );
    return 0;
}

2voto

Steven Warner Punkte 11

Für Linux

Sie können auch /proc/self/statm verwenden, um eine einzelne Zeile mit Zahlen zu erhalten, die wichtige Informationen über den Prozessspeicher enthalten, was schneller geht, als eine lange Liste von gemeldeten Informationen durchzugehen, wie Sie sie von proc/self/status erhalten

Véase proc(5)

/proc/[pid]/statm

    Provides information about memory usage, measured in pages.
    The columns are:

        size       (1) total program size
                   (same as VmSize in /proc/[pid]/status)
        resident   (2) resident set size
                   (same as VmRSS in /proc/[pid]/status)
        shared     (3) number of resident shared pages (i.e., backed by a file)
                   (same as RssFile+RssShmem in /proc/[pid]/status)
        text       (4) text (code)
        lib        (5) library (unused since Linux 2.6; always 0)
        data       (6) data + stack
        dt         (7) dirty pages (unused since Linux 2.6; always 0)

1voto

Marisa Kirisame Punkte 156

Unter Linux kann/sollte man "Total Available Physical Memory" nicht mit SysInfo's freeram oder durch Arithmetik auf totalram ermitteln.

Der empfohlene Weg, dies zu tun, ist das Lesen von proc/meminfo unter Angabe von [kernel/git/torvalds/linux.git, /proc/meminfo: Bereitstellung des geschätzten verfügbaren Speichers](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773) :

Viele Programme zum Lastausgleich und zur Verteilung der Arbeitslast prüfen /proc/meminfo, um um abzuschätzen, wie viel freier Speicher verfügbar ist. Sie tun dies im Allgemeinen durch Addition von "frei" und "zwischengespeichert", was vor zehn Jahren noch in Ordnung war, aber heute garantiert falsch ist.

Es ist bequemer, eine solche Schätzung in /proc/meminfo bereitzustellen. Wenn sich die Dinge in Zukunft ändern, müssen wir sie nur an einer Stelle ändern.

Eine Möglichkeit dazu ist _Adam Rosenfields Antwort auf Wie bestimmt man die Größe des Linux-System-RAM in C++?_ Vorschlag: Lesen Sie die Datei, und verwenden Sie fscanf, um die Zeile zu erfassen (aber anstatt nach MemTotal suchen Sie nach MemAvailable)

Wenn Sie die Gesamtmenge des verwendeten physischen Speichers ermitteln wollen, sollten Sie nicht freeram von totalram subtrahieren, sondern memavailable von memtotal, um das zu erhalten, was top oder htop Ihnen sagen.

0voto

Salman Ghaffar Punkte 19

Ich habe den folgenden Code in meinem C++-Projekt verwendet und er hat gut funktioniert:

static HANDLE self;
static int numProcessors;
SYSTEM_INFO sysInfo;

double percent;

numProcessors = sysInfo.dwNumberOfProcessors;

//Getting system times information
FILETIME SysidleTime;
FILETIME SyskernelTime; 
FILETIME SysuserTime; 
ULARGE_INTEGER SyskernelTimeInt, SysuserTimeInt;
GetSystemTimes(&SysidleTime, &SyskernelTime, &SysuserTime);
memcpy(&SyskernelTimeInt, &SyskernelTime, sizeof(FILETIME));
memcpy(&SysuserTimeInt, &SysuserTime, sizeof(FILETIME));
__int64 denomenator = SysuserTimeInt.QuadPart + SyskernelTimeInt.QuadPart;  

//Getting process times information
FILETIME ProccreationTime, ProcexitTime, ProcKernelTime, ProcUserTime;
ULARGE_INTEGER ProccreationTimeInt, ProcexitTimeInt, ProcKernelTimeInt, ProcUserTimeInt;
GetProcessTimes(self, &ProccreationTime, &ProcexitTime, &ProcKernelTime, &ProcUserTime);
memcpy(&ProcKernelTimeInt, &ProcKernelTime, sizeof(FILETIME));
memcpy(&ProcUserTimeInt, &ProcUserTime, sizeof(FILETIME));
__int64 numerator = ProcUserTimeInt.QuadPart + ProcKernelTimeInt.QuadPart;
//QuadPart represents a 64-bit signed integer (ULARGE_INTEGER)

percent = 100*(numerator/denomenator);

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X