프로세스 안에서 CPU / memory 소비량 알아내는 법

어플리케이션을 실행하는 중에 밑의 내용을 알아낼 수 있는 방법이 있을까요?

  • 사용 가능한 virtual memory 크기
  • 지금 쓰고 있는 Virtual memory 크기
  • 이 프로세스가 쓰고 있는 Virtual memory 크기

  • 사용 가능한 RAM 크기
  • 지금 쓰고 있는 RAM 크기
  • 이 프로세스가 쓰고 있는 RAM 크기

  • 지금 CPU 사용률
  • 이 프로세스가 쓰고 있는 CPU 사용률

제 코드는 windows와 linux에서 실행됩니다. 정확한 정보를 얻을 수 없어서 여기에 질문합니다.

1답변

  • 좋아요

    0

    싫어요
    채택취소하기

    Windows

    일부는 WIN32 API에서 제공하고 있습니다. 그 외의 것은 PDH(Performance Data Helper) library에서 제공합니다.

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

    TotalPageFile는 보통 swap file+RAM을 의미하지만 여기서는 좀 다르게 쓰였습니다.

    • 지금쓰고 있는 Virtual Memory: 전체 Virtual Memory에 다음을 추가합니다.
        DWORDLONG virtualMemUsed = memInfo.ullTotalPageFile - memInfo.ullAvailPageFile;
    
    • 이 프로세스가 쓰고 있는 Virtual Memory:
    #include "windows.h"
    #include "psapi.h"
    
    PROCESS_MEMORY_COUNTERS_EX pmc;
    GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
    SIZE_T virtualMemUsedByMe = pmc.PrivateUsage;
    
    • 전체 Physical Memory (RAM): 전체 Virtual Memory에 다음을 추가합니다
    DWORDLONG totalPhysMem = memInfo.ullTotalPhys;
    
    • 지금 쓰고 있는 Physical Memory: 전체 Virtual Memory에 다음을 추가합니다
    DWORDLONG physMemUsed = memInfo.ullTotalPhys - memInfo.ullAvailPhys;
    
    • 이 프로세스가 쓰고 있는 Physical Memory: 이 프로세스가 쓰고 있는 Virtual Memory에 다음을 추가합니다
    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);
        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:
    #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

    • 전체 Virtual Memory:
    #include "sys/types.h"
    #include "sys/sysinfo.h"
    
    struct sysinfo memInfo;
    
    sysinfo (&memInfo);
    long long totalVirtualMem = memInfo.totalram;
    totalVirtualMem += memInfo.totalswap;
    totalVirtualMem *= memInfo.mem_unit;
    
    • 지금 쓰고 있는 Virtual Memory: 전체 Virtual Memory에 다음을 추가합니다.
    long long virtualMemUsed = memInfo.totalram - memInfo.freeram;
    virtualMemUsed += memInfo.totalswap - memInfo.freeswap;
    virtualMemUsed *= memInfo.mem_unit;
    
    • 이 프로세스가 쓰고 있는 Virtual Memory:
    #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(){ //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;
    }
    
    • 전체 Physical Memory (RAM): 전체 Virtual Memory에 다음을 추가하세요
    long long totalPhysMem = memInfo.totalram;
    totalPhysMem *= memInfo.mem_unit;
    
    • 지금 쓰고 있는 Physical Memory: 전체 Virtual Memory에 다음을 추가하세요
    long long physMemUsed = memInfo.totalram - memInfo.freeram;
    physMemUsed *= memInfo.mem_unit;
    
    • 이 프로세스가 쓰고 있는 Physical Memory: 이 프로세스가 쓰고 있는 Virtual MemorygetValue()를 다음과 같이 바꾸세요
    int getValue(){ //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){
            //오버플로우 detection
            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){
            //오버플로우 감지
            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;
    }
    
    • 안녕하세요. 작성해주신 코드를 사용해보려 했습니다. PROCESS_MEMORY_COUNTERS_EX pmc;로 선언해주셨는데 GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)); 여기서 중간에 들어갈 파라미터가 &pmc의 형인 PROCESS_MEMORY_COUNTERS_EX가 아니라 PROCESS_MEMORY_COUNTERS라서 맞지 않아 에러가 발생합니다. 정동규 2018.1.22 16:13

ᕕ( ᐛ )ᕗ
로그인이 필요합니다

작성한 답변에 다른 개발자들이 댓글을 작성하거나 댓글에 좋아요/싫어요를 할 수 있기 때문에 계정을 필요로 합니다.