如何确定CPU和内存消耗从进程中? [英] How to determine CPU and memory consumption from inside a process?
问题描述
我曾经从正在运行的应用程序中确定以下性能参数的任务:
I once had the task of determining the following performance parameters from inside a running application:
- 总可用虚拟内存
- 目前使用的虚拟内存
- 目前使用的过程中我的虚拟内存
- 总可用RAM
- 目前使用的RAM
- 目前使用的我的过程RAM
- 目前使用的CPU%
- 目前使用的我的过程%的CPU
在code必须在Windows和Linux上运行。尽管这似乎是一个标准的任务,发现在手册中的必要信息(WIN32 API,GNU文档),以及在互联网上花了我好几天,因为有对这个话题这么多的不完整/不正确/过时的信息,以便发现在那里。
The code had to run on Windows and Linux. Even though this seems to be a standard task, finding the necessary information in the manuals (WIN32 API, GNU docs) as well as on the Internet took me several days, because there's so much incomplete/incorrect/outdated information on this topic to be found out there.
为了挽救他人通过同样的麻烦去,我认为这将是一个好主意,在这里收集所有分散的信息以及我发现了什么的试验和错误在一个地方。
In order to save others from going through the same trouble, I thought it would be a good idea to collect all the scattered information plus what I found by trial and error here in one place.
推荐答案
有些上面的数值很容易可以从相应的WIN32 API,我就一一列举的完整性。然而,其他人需要从性能数据助手libary(PDH),这是一个有点直观,并采取了很多痛苦的尝试和错误的去上班获得的。 (至少我花了相当长一段时间,也许我一直只是有点笨...)
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...)
注:为了清楚所有的错误检查已经从以下code省略。请检查返回$ C $ ... CS!
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;
注:TotalPageFile这个名字是有点误导这里。在现实中,这个参数给出了虚拟内存大小,这是交换文件的大小加上安装的RAM。
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.
目前使用的虚拟内存:
同样code,如总的虚拟内存,然后
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;
搜索结果
-
总的物理内存(RAM):
Total Physical Memory (RAM):
同样code,如总的虚拟内存,然后
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:
同样code,如目前使用的当前进程虚拟内存,然后
Same code as in "Virtual Memory currently used by current process" and then
SIZE_T physMemUsedByMe = pmc.WorkingSetSize;
搜索结果
-
CPU目前使用的:
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目前使用的当前进程:
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上,似乎在一个明显的选择是使用POSIX API,如使用getrusage()等等。我花了一些时间,试图得到这个工作,但从来没有得到有意义的值。当我终于检查内核源代码本身,我发现,显然这些API还没有完全作为Linux内核2.6!?
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!?
在最后,我通过阅读伪文件系统/ proc和内核调用的结合得到了所有的值。
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:
同样code,如总的虚拟内存,然后
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){
// 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):
Total Physical Memory (RAM):
同样code,如总的虚拟内存,然后
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:
同样code,如总的虚拟内存,然后
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:
更改的getValue()中的如下目前使用的当前进程虚拟内存:
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目前使用的:
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 %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目前使用的当前进程:
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;
}
我会假设,一些Linux的code也适用于对Unix系统,除了读取/ proc虚拟文件系统的部分。也许在Unix这些部件可以通过使用getrusage()和类似的功能所取代?
如果有人用Unix的诀窍可以编辑这个答案,并填写详细信息?!
I would assume, that some of the Linux code also works for the Unixes, except for the parts that read the /proc pseudo-filesystem. Perhaps on Unix these parts can be replaced by getrusage() and similar functions? If someone with Unix know-how could edit this answer and fill in the details?!
这篇关于如何确定CPU和内存消耗从进程中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!