How to determine CPU and memory consumption from inside a process

来源:互联网 发布:电子商务软件有哪些 编辑:程序博客网 时间:2024/06/07 15:10
  • Total virtual memory available
  • Virtual memory currently used
  • Virtual memory currently used by my process
  • Total RAM available
  • RAM currently used
  • RAM currently used by my process
  • % CPU currently used
  • % CPU currently used by my process

Windows

Some of the above values are easily available from the appropriate WIN32 API, I just list them here for completeness. Others, however, need to be obtained from the Performance Data Helper libary (PDH), which is a bit "unintuitive" and takes a lot of painful trial and error to get to work. (At least it took me quite a while, perhaps I've been only a bit stupid...)

Note: for clarity all error checking has been omitted from the following code. Do check the return codes...!


  • Total Virtual Memory:
    #include "windows.h"        MEMORYSTATUSEX memInfo;    memInfo.dwLength = sizeof(MEMORYSTATUSEX);    GlobalMemoryStatusEx(&memInfo);    DWORDLONG totalVirtualMem = memInfo.ullTotalPageFile;

Note: The name "TotalPageFile" is a bit misleading here. In reality this parameter gives the "Virtual Memory Size", which is size of swap file plus installed RAM.

  • Virtual Memory currently used:

Same code as in "Total Virtual Memory" and then

    DWORDLONG virtualMemUsed = memInfo.ullTotalPageFile - memInfo.ullAvailPageFile;
  • Virtual Memory currently used by current process:
    #include "windows.h"    #include "psapi.h"        PROCESS_MEMORY_COUNTERS_EX pmc;    GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));    SIZE_T virtualMemUsedByMe = pmc.PrivateUsage;



  • Total Physical Memory (RAM):

Same code as in "Total Virtual Memory" and then

    DWORDLONG totalPhysMem = memInfo.ullTotalPhys;
  • Physical Memory currently used:

Same code as in "Total Virtual Memory" and then

    DWORDLONG physMemUsed = memInfo.ullTotalPhys - memInfo.ullAvailPhys;
  • Physical Memory currently used by current process:

Same code as in "Virtual Memory currently used by current process" and then

    SIZE_T physMemUsedByMe = pmc.WorkingSetSize;



  • CPU currently used:
    #include "TCHAR.h"    #include "pdh.h"        static PDH_HQUERY cpuQuery;    static PDH_HCOUNTER cpuTotal;        void init(){        PdhOpenQuery(NULL, NULL, &cpuQuery);        PdhAddCounter(cpuQuery, L"\\Processor(_Total)\\% Processor Time", NULL, &cpuTotal);        PdhCollectQueryData(cpuQuery);    }        double getCurrentValue(){        PDH_FMT_COUNTERVALUE counterVal;            PdhCollectQueryData(cpuQuery);        PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal);        return counterVal.doubleValue;    }
  • CPU currently used by current process:
    #include "windows.h"        static ULARGE_INTEGER lastCPU, lastSysCPU, lastUserCPU;    static int numProcessors;    static HANDLE self;        void init(){        SYSTEM_INFO sysInfo;        FILETIME ftime, fsys, fuser;            GetSystemInfo(&sysInfo);        numProcessors = sysInfo.dwNumberOfProcessors;            GetSystemTimeAsFileTime(&ftime);        memcpy(&lastCPU, &ftime, sizeof(FILETIME));            self = GetCurrentProcess();        GetProcessTimes(self, &ftime, &ftime, &fsys, &fuser);        memcpy(&lastSysCPU, &fsys, sizeof(FILETIME));        memcpy(&lastUserCPU, &fuser, sizeof(FILETIME));    }        double getCurrentValue(){        FILETIME ftime, fsys, fuser;        ULARGE_INTEGER now, sys, user;        double percent;            GetSystemTimeAsFileTime(&ftime);        memcpy(&now, &ftime, sizeof(FILETIME));            GetProcessTimes(self, &ftime, &ftime, &fsys, &fuser);        memcpy(&sys, &fsys, sizeof(FILETIME));        memcpy(&user, &fuser, sizeof(FILETIME));        percent = (sys.QuadPart - lastSysCPU.QuadPart) +            (user.QuadPart - lastUserCPU.QuadPart);        percent /= (now.QuadPart - lastCPU.QuadPart);        percent /= numProcessors;        lastCPU = now;        lastUserCPU = user;        lastSysCPU = sys;            return percent * 100;    }

 

Linux

On Linux the choice that seemed obvious at first was to use the POSIX APIs like getrusage() etc. I spent some time trying to get this to work, but never got meaningful values. When I finally checked the kernel sources themselves, I found out that apparently these APIs are not yet completely implemented as of Linux kernel 2.6!?

In the end I got all values via a combination of reading the pseudo-filesystem /proc and kernel calls.

  • Total Virtual Memory:
    #include "sys/types.h"    #include "sys/sysinfo.h"        struct sysinfo memInfo;        sysinfo (&memInfo);    long long totalVirtualMem = memInfo.totalram;    //Add other values in next statement to avoid int overflow on right hand side...    totalVirtualMem += memInfo.totalswap;    totalVirtualMem *= memInfo.mem_unit;
  • Virtual Memory currently used:

Same code as in "Total Virtual Memory" and then

    long long virtualMemUsed = memInfo.totalram - memInfo.freeram;    //Add other values in next statement to avoid int overflow on right hand side...    virtualMemUsed += memInfo.totalswap - memInfo.freeswap;    virtualMemUsed *= memInfo.mem_unit;
  • Virtual Memory currently used by current process:
    #include "stdlib.h"    #include "stdio.h"    #include "string.h"        int parseLine(char* line){        int i = strlen(line);        while (*line < '0' || *line > '9') line++;        line[i-3] = '\0';        i = atoi(line);        return i;    }        int getValue(){ //Note: this value is in KB!        FILE* file = fopen("/proc/self/status", "r");        int result = -1;        char line[128];            while (fgets(line, 128, file) != NULL){            if (strncmp(line, "VmSize:", 7) == 0){                result = parseLine(line);                break;            }        }        fclose(file);        return result;    }



  • Total Physical Memory (RAM):

Same code as in "Total Virtual Memory" and then

    long long totalPhysMem = memInfo.totalram;    //Multiply in next statement to avoid int overflow on right hand side...    totalPhysMem *= memInfo.mem_unit;
  • Physical Memory currently used:

Same code as in "Total Virtual Memory" and then

    long long physMemUsed = memInfo.totalram - memInfo.freeram;    //Multiply in next statement to avoid int overflow on right hand side...    physMemUsed *= memInfo.mem_unit;
  • Physical Memory currently used by current process:

Change getValue() in "Virtual Memory currently used by current process" as follows:

    int getValue(){ //Note: this value is in KB!        FILE* file = fopen("/proc/self/status", "r");        int result = -1;        char line[128];            while (fgets(line, 128, file) != NULL){            if (strncmp(line, "VmRSS:", 6) == 0){                result = parseLine(line);                break;            }        }        fclose(file);        return result;    }



  • CPU currently used:
    #include "stdlib.h"    #include "stdio.h"    #include "string.h"        static unsigned long long lastTotalUser, lastTotalUserLow, lastTotalSys, lastTotalIdle;        void init(){        FILE* file = fopen("/proc/stat", "r");        fscanf(file, "cpu %Ld %Ld %Ld %Ld", &lastTotalUser, &lastTotalUserLow,            &lastTotalSys, &lastTotalIdle);        fclose(file);    }        double getCurrentValue(){        double percent;        FILE* file;        unsigned long long totalUser, totalUserLow, totalSys, totalIdle, total;            file = fopen("/proc/stat", "r");        fscanf(file, "cpu %Ld %Ld %Ld %Ld", &totalUser, &totalUserLow,            &totalSys, &totalIdle);        fclose(file);            if (totalUser < lastTotalUser || totalUserLow < lastTotalUserLow ||            totalSys < lastTotalSys || totalIdle < lastTotalIdle){            //Overflow detection. Just skip this value.            percent = -1.0;        }        else{            total = (totalUser - lastTotalUser) + (totalUserLow - lastTotalUserLow) +                (totalSys - lastTotalSys);            percent = total;            total += (totalIdle - lastTotalIdle);            percent /= total;            percent *= 100;        }            lastTotalUser = totalUser;        lastTotalUserLow = totalUserLow;        lastTotalSys = totalSys;        lastTotalIdle = totalIdle;            return percent;    }
  • CPU currently used by current process:
    #include "stdlib.h"    #include "stdio.h"    #include "string.h"    #include "sys/times.h"    #include "sys/vtimes.h"        static clock_t lastCPU, lastSysCPU, lastUserCPU;    static int numProcessors;        void init(){        FILE* file;        struct tms timeSample;        char line[128];            lastCPU = times(&timeSample);        lastSysCPU = timeSample.tms_stime;        lastUserCPU = timeSample.tms_utime;            file = fopen("/proc/cpuinfo", "r");        numProcessors = 0;        while(fgets(line, 128, file) != NULL){            if (strncmp(line, "processor", 9) == 0) numProcessors++;        }        fclose(file);    }        double getCurrentValue(){        struct tms timeSample;        clock_t now;        double percent;            now = times(&timeSample);        if (now <= lastCPU || timeSample.tms_stime < lastSysCPU ||            timeSample.tms_utime < lastUserCPU){            //Overflow detection. Just skip this value.            percent = -1.0;        }        else{            percent = (timeSample.tms_stime - lastSysCPU) +                (timeSample.tms_utime - lastUserCPU);            percent /= (now - lastCPU);            percent /= numProcessors;            percent *= 100;        }        lastCPU = now;        lastSysCPU = timeSample.tms_stime;        lastUserCPU = timeSample.tms_utime;            return percent;    }

 

GlobalMemoryStatus

GlobalMemoryStatus,Win32 API函数。

此函数用来获得当前可用的物理和虚拟内存信息,函数定义为:

?

1

2

3

4

VOID GlobalMemoryStatus

(

LPMEMORYSTATUS lpBuffer

);

此函数无返回值,参数是一个指向名为MEMORYSTATUS的结构的指针。函数的返回信息会被存储在MEMORYSTATUS结构中。

此函数用来替代用来支持16位应用程序的GetFreeSpace函数。

2G以上内存建议使用GlobalMemoryStatusEx函数代替(2~4G需要链接器/LARGEADDRESSAWARE选项,4G以上不支持)

应用程序应该在申请内存前调用此函数以防止影响到其他程序运行。

这个函数的返回值是动态的,并且可能返回相同的值。

关于MEMORYSTATUS结构:

结构定义:

?

1

2

3

4

5

6

7

8

9

10

typedefstruct _MEMORYSTATUS {// mst

DWORD dwLength; // sizeof(MEMORYSTATUS)

DWORD dwMemoryLoad; // percent of memory in use

DWORD dwTotalPhys; // bytes of physical memory

DWORD dwAvailPhys; // free physical memory bytes

DWORD dwTotalPageFile; // bytes of paging file

DWORD dwAvailPageFile; // free bytes of paging file

DWORD dwTotalVirtual; // user bytes of address space

DWORD dwAvailVirtual; // free user bytes

} MEMORYSTATUS, *LPMEMORYSTATUS;

结构成员的含义:

dwLength

MEMORYSTATUS结构的大小,在调GlobalMemoryStatus函数前用sizeof()函数求得,用来供函数检测结构的版本。

dwMemoryLoad

返回一个介于0~100之间的值,用来指示当前系统内存的使用率。

dwTotalPhys

返回总的物理内存大小,以字节(byte)为单位。

dwAvailPhys

返回可用的物理内存大小,以字节(byte)为单位。

dwTotalPageFile

显示可以存在页面文件中的字节数。注意这个数值并不表示在页面文件在磁盘上的真实物理大小。

dwAvailPageFile

返回可用的页面文件大小,以字节(byte)为单位。

dwTotalVirtual

返回调用进程的用户模式部分的全部可用虚拟地址空间,以字节(byte)为单位。

dwAvailVirtual

返回调用进程的用户模式部分的实际自由可用的虚拟地址空间,以字节(byte)为单位。

MEMORYSTATUS结构,

结构的定义如下:

?

1

2

3

4

5

6

7

8

9

10

MEMORYSTATUS STRUCT

dwLength            DWORD      ?     ;本结构的长度

dwMemoryLoad      DWORD      ?     ;已用内存的百分比

dwTotalPhys       DWORD      ?     ;物理内存总量

dwAvailPhys       DWORD      ?     ;可用物理内存

dwTotalPageFile   DWORD      ?     ;交换文件总的大小

dwAvailPageFile   DWORD      ?     ;交换文件中空闲部分大小

dwTotalVirtual    DWORD      ?     ;用户可用的地址空间

dwAvailVirtual    DWORD      ?     ;当前空闲的地址空间

MEMORYSTATUS ENDS

 

转载地址:http://stackoverflow.com/questions/63166/how-to-determine-cpu-and-memory-consumption-from-inside-a-process

0 0