SORU
15 EYLÜL 2008, PAZARTESİ


Nasıl bir süreç içinde CPU ve bellek kullanımı belirlemek için?

Bir zamanlar ben de çalışan bir uygulama içinde aşağıdaki performans parametrelerini belirleme görevi vardı:

  • Toplam sanal bellek
  • Sanal bellek kullanılmakta
  • Sanal bellek şu anda benim bir süreç tarafından kullanılır
  • RAM kullanılabilir toplam
  • RAM kullanılmakta
  • RAM şu anda benim bir süreç tarafından kullanılır
  • % CPU kullanılmakta
  • % CPU şu anda benim bir süreç tarafından kullanılır

Kodu Windows ve Linux üzerinde çalıştırmak için. Olsa bile bu gibi görünüyor bir standart görev, bulmak gerekli bilgileri kılavuzları (WİN32 API, GNU docs) yanı sıra İnternet aldı beni birkaç gün, çünkü burada çok fazla eksik/yanlış/güncel bilgi bu konuyu öğrendi.

Aynı sorun geçiyor diğerlerini kurtarmak için, tek bir yerde deneme yanılma burada ne buldum tüm dağınık bilgileri artı toplamak için iyi bir fikir olacağını düşündüm.

CEVAP
15 EYLÜL 2008, PAZARTESİ


Windows

Yukarıda bazı değerler uygun win 32 API, ben sadece onları buraya bütünlüğü için listeden kolayca kullanılabilir. Diğerleri ise, biraz "" ve ağrılı deneme yanılma bir sürü iş alır. sezgisel olmayan bir Performans Verisi Yardımcısı kütüphane (RAF), elde edilmesi gerekir (En azından bana biraz zaman aldı, belki de sadece biraz aptal...) oldum

Not: netlik tüm hata denetimi aşağıdaki kodu. ihmal edilmiş Check dönüş kodları...!


  • Toplam Sanal Bellek:

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

Not: adı "TotalPageFile" biraz yanıltıcı geldi. Gerçekte bu parametre verir "Sanal Bellek Boyutu takas boyutu artı RAM. dosya yüklü olduğu",

  • Sanal Bellek şu anda kullanılan:

Aynı kod olarak "Toplam Sanal Bellek" ve sonra


    DWORDLONG virtualMemUsed = memInfo.ullTotalPageFile - memInfo.ullAvailPageFile;
  • Sanal Bellek şu anda geçerli işlem tarafından kullanılan:

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



  • (RAM) toplam Fiziksel Bellek:

Aynı kod olarak "Toplam Sanal Bellek" ve sonra


    DWORDLONG totalPhysMem = memInfo.ullTotalPhys;
  • Şu anda kullanılan fiziksel Bellek:

Aynı kod olarak "Toplam Sanal Bellek" ve sonra


    DWORDLONG physMemUsed = memInfo.ullTotalPhys - memInfo.ullAvailPhys;
  • Fiziksel Bellek şu anda geçerli işlem tarafından kullanılan:

Aynı kod olarak "Sanal Bellek şu anda geçerli işlem tarafından kullanılan" ve sonra


    SIZE_T physMemUsedByMe = pmc.WorkingSetSize;



  • CPU şu anda kullanılan:

    #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 şu anda geçerli işlem tarafından kullanılan:

    #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 üzerinde açık görünen seçim ilk getrusage gibi POSIX API kullanmak() vb. Bir süre bu işe almak için harcadım, ama hiç anlamlı değerler var. Sonunda çekirdek kaynaklarını kendileri kontrol, görünüşe göre bu API Henüz tamamen Linux çekirdeği olarak uygulanmadı öğrendim 2.6!?

Sonunda pseudo-filesystem /proc ve çekirdek aramalar Okuma bir kombinasyonu yoluyla tüm değerler var.

  • Toplam Sanal Bellek:

    #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;
  • Sanal Bellek şu anda kullanılan:

Aynı kod olarak "Toplam Sanal Bellek" ve sonra


    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;
  • Sanal Bellek şu anda geçerli işlem tarafından kullanılan:

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



  • (RAM) toplam Fiziksel Bellek:

Aynı kod olarak "Toplam Sanal Bellek" ve sonra


    long long totalPhysMem = memInfo.totalram;
    //Multiply in next statement to avoid int overflow on right hand side...
    totalPhysMem *= memInfo.mem_unit;
  • Şu anda kullanılan fiziksel Bellek:

Aynı kod olarak "Toplam Sanal Bellek" ve sonra


    long long physMemUsed = memInfo.totalram - memInfo.freeram;
    //Multiply in next statement to avoid int overflow on right hand side...
    physMemUsed *= memInfo.mem_unit;
  • Fiziksel Bellek şu anda geçerli işlem tarafından kullanılan:

"Sanal Bellek şu anda geçerli işlem tarafından kullanılan aşağıdaki gibidir:". getValue (değişim)


    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 şu anda kullanılan:

    #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 şu anda geçerli işlem tarafından kullanılan:

    #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: Diğer Platformlar

Linux kodlarını da /proc pseudo-filesystem okuma parçaları dışında Unix için çalışıyor, tahmin ediyorum ki. Belki bu parçalar getrusage tarafından değiştirilebilir Unıx() ve benzeri fonksiyonları? Unıx olan birinin bu cevabı Düzenle olabilir know-how ve bilgileri doldurun?

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Amir Parmar

    Amir Parmar

    25 Kasım 2010
  • FOSDEM

    FOSDEM

    13 Ocak 2009
  • KliptOut KwazeeKilla

    KliptOut Kwa

    24 ŞUBAT 2010