亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何從進程內部確定CPU和內存消耗?

如何從進程內部確定CPU和內存消耗?

慕桂英546537 2019-06-06 10:44:36
如何從進程內部確定CPU和內存消耗?我曾經負責從運行中的應用程序中確定以下性能參數:可用虛擬內存總量當前使用的虛擬內存我的進程當前使用的虛擬內存可用內存總數Ram目前使用我的進程目前使用的RAM目前使用的CPU百分比我的進程當前使用的CPU%代碼必須在Windows和Linux上運行。盡管這似乎是一項標準任務,但在手冊(Win 32 API,GNU docs)中以及在Internet上找到必要的信息花了我幾天的時間,因為關于這個主題有很多不完整/不正確/過時的信息要找出來。為了避免其他人經歷同樣的麻煩,我認為收集所有零散的信息,再加上我在一個地方經過反復試驗發現的信息,是個好主意。
查看完整描述

3 回答

?
侃侃無極

TA貢獻2051條經驗 獲得超10個贊

上面的一些值很容易從適當的Win 32 API中獲得,我只是在這里列出它們的完整性。然而,另一些則需要從性能數據幫助庫(PDH)中獲得,這有點“不直觀”,需要大量痛苦的嘗試和錯誤才能開始工作。(至少花了我一段時間,也許我只是有點傻.)

注意:為了清楚起見,以下代碼省略了所有錯誤檢查。檢查返回碼.!


  • 總虛擬內存:

    #include "windows.h"MEMORYSTATUSEX memInfo;memInfo.dwLength = sizeof(MEMORYSTATUSEX);GlobalMemoryStatusEx(&memInfo);
    DWORDLONG totalVirtualMem = memInfo.ullTotalPageFile;

    注意:這里的名字“TotalPageFile”有點誤導。實際上,這個參數給出了“虛擬內存大小”,即交換文件加上已安裝RAM的大小。

  • 當前使用的虛擬內存:

    與“總虛擬內存”中的代碼相同,然后

    DWORDLONG virtualMemUsed = memInfo.ullTotalPageFile - memInfo.ullAvailPageFile;
  • 當前進程當前使用的虛擬內存:

    #include "windows.h"#include "psapi.h"PROCESS_MEMORY_COUNTERS_EX pmc;GetProcessMemoryInfo(GetCurrentProcess(), 
    &pmc, sizeof(pmc));SIZE_T virtualMemUsedByMe = pmc.PrivateUsage;



  • 總物理內存(RAM):

    與“總虛擬內存”中的代碼相同,然后

    DWORDLONG totalPhysMem = memInfo.ullTotalPhys;
  • 目前使用的物理內存:

    Same code as in "Total Virtual Memory" and thenDWORDLONG physMemUsed = memInfo.ullTotalPhys - memInfo.ullAvailPhys;
  • 當前進程當前使用的物理內存:

    與“當前進程當前使用的虛擬內存”中的代碼相同,然后

    SIZE_T physMemUsedByMe = pmc.WorkingSetSize;



  • 目前使用的CPU:

    #include "TCHAR.h"#include "pdh.h"static PDH_HQUERY cpuQuery;static PDH_HCOUNTER cpuTotal;void init(){
        PdhOpenQuery(NULL, NULL, &cpuQuery);
        // You can also use L"\\Processor(*)\\% Processor Time" and get individual CPU values with
         PdhGetFormattedCounterArray()
        PdhAddEnglishCounter(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:

    #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

在linux上,一開始似乎很明顯的選擇是使用POSIX API,如getrusage()等。我花了一些時間試著讓它發揮作用,但卻沒有得到有意義的價值。當我最終檢查內核源代碼時,我發現這些API顯然還沒有在Linux2.6內核中完全實現!

最后,我通過合并讀取偽文件系統獲得了所有的值。/proc和內核調用。

  • 總虛擬內存:

    #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;
  • 當前使用的虛擬內存:

    與“總虛擬內存”中的代碼相同,然后

    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;
  • 當前進程當前使用的虛擬內存:

    #include "stdlib.h"#include "stdio.h"#include "string.h"int parseLine(char* line){
        // This assumes that a digit will be found and the line ends in " Kb".
        int i = strlen(line);
        const char* p = line;
        while (*p <'0' || *p > '9') p++;
        line[i-3] = '\0';
        i = atoi(p);
        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;}



  • 總物理內存(RAM):

    與“總虛擬內存”中的代碼相同,然后

    long long totalPhysMem = memInfo.totalram;//Multiply in next statement to avoid int overflow on right hand
     side...totalPhysMem *= memInfo.mem_unit;
  • 目前使用的物理內存:

    與“總虛擬內存”中的代碼相同,然后

    long long physMemUsed = memInfo.totalram - memInfo.freeram;//Multiply in next statement to avoid int overflow 
    on right hand side...physMemUsed *= memInfo.mem_unit;
  • 當前進程當前使用的物理內存:

    在“當前進程當前使用的虛擬內存”中更改getValue()如下:

    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:

    #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 %llu %llu %llu %llu", &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 %llu %llu %llu %llu", &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:

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

Todo:其他平臺

我假設,除了讀取/proc偽文件系統的部分之外,一些Linux代碼也適用于unix。也許在unix上,這些部件可以由getrusage()還有類似的功能?如果有Unix技術的人可以編輯這個答案并填寫詳細信息?!


查看完整回答
反對 回復 2019-06-06
  • 3 回答
  • 0 關注
  • 966 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號