|
Thanks Dudi for sharing the code. I'm puzzled for the result of CPU usage.
Here lists my code:
while(1){
vector <int> vPid;
GetPidByName(vPid,"dllhost.exe");
for(int j=0;j<vPid.size(); j++)
{
int nUsage = g_Usage.GetCpuUsage(vPid.at(j));
printf("pid: %d cpusage: %d\n",vPid.at(j), nUsage);
}
sleep(5000);
}
Very simple. But I found that sometimes the result(nUsage) is much more than 100,for example: 56254,56573, in fact, the usage shown in TaskManager is just between 10%~30% generally. I've read some of the posts,it seems someone meet the sample problem with me.Maybe the reason is the number of cpu?or about hyperthread? I know few of this field. I only know that my program is tested on a multi-cpu server,but I don't know exactly infomation.And I'v found that when the result is less than 100%,it is usually more than the result get from TaskManager. I don't know why. Who can explain that ?
|
|
|
|
|
Hi, i must thank the author for the shared code....i was in great need of reseting a COM+ that eats CPU alive after a few hours ....
Well i have your same problem .....I tested the application on a Intel P4 with
hyperthreading and when i querry the CPU usage i get doubled results....It
seems that by dividing the returned result by 2 the problem is solved;
but i have no clue what would happen in case of dual processor environments
with hyperthreading...
This problem goes with GetCPUUsage(szProcessName) and GetCPUUsage(processID), ..
the first one(GetCPUUsage) seems to work OK
On a single processor environment without HT everything is FINE....
THX a lot
Greetings from Daos
|
|
|
|
|
Hi ,
I want to find the other process memory . Like what is shown in the task manager. Can any give me a clue how find memory occupied by a process by giving its process.
Thanks
Regards
Sai Kumar
|
|
|
|
|
Someone has already asked me that question and this is what i wrote:
Well,
The process object has a counter, named "Virtual Bytes", whose index is 174.
Since the counter size is 4 bytes long, you need to change the declaration of "CPerfCounters<longlong> PerfCounters;" to "CPerfCounters<long> PerfCounters;".
However, i don't know if that counter gives what you need.
|
|
|
|
|
I am not getting the memory size what is shown in the taskmanager. IT is different. I gave dwCpuUsageIndex=174 . Is it correct
|
|
|
|
|
Well, the counter index is 180 which stands for "working set" in the performance counters.
It is 4 byte long therefore change the declaration CPerfCounters<LONGLONG> to CPerfCounters<LONG>.
The data is in bytes so don't forget to devide it by 1024 in order to display it in KB.
|
|
|
|
|
Great work!!
your CPerfCounters class is really good!
so using your CPU class method, memory counter on process (only by pid there) will be:
<br />
#ifndef _MEMORYUSAGE_H<br />
#define _MEMORYUSAGE_H<br />
<br />
#include < windows.h ><br />
<br />
class CMemoryUsage<br />
{<br />
public:<br />
CMemoryUsage();<br />
virtual ~CMemoryUsage();<br />
<br />
int GetMemoryUsage(DWORD dwProcessID);<br />
BOOL EnablePerformaceCounters(BOOL bEnable = TRUE);<br />
<br />
private:<br />
bool m_bFirstTime;<br />
};<br />
<br />
#endif<br />
<br />
#include "StdAfx.h"<br />
#include < atlbase.h ><br />
#include "memoryusage.h"<br />
<br />
#pragma pack(push,8)<br />
#include "PerfCounters.h"<br />
#pragma pack(pop)<br />
<br />
#define PROCESS_OBJECT_INDEX 230 // 'Process' object<br />
#define MEMORY_OBJECT_INDEX 180 // 'Working Set' object<br />
<br />
<br />
CMemoryUsage::CMemoryUsage()<br />
{<br />
m_bFirstTime = true;<br />
}<br />
<br />
CMemoryUsage::~CMemoryUsage()<br />
{<br />
}<br />
<br />
BOOL CMemoryUsage::EnablePerformaceCounters(BOOL bEnable)<br />
{<br />
CRegKey regKey;<br />
if (regKey.Open(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\PerfOS\\Performance") != ERROR_SUCCESS)<br />
return FALSE;<br />
<br />
regKey.SetValue(!bEnable, "Disable Performance Counters");<br />
regKey.Close();<br />
<br />
if (regKey.Open(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\PerfProc\\Performance") != ERROR_SUCCESS)<br />
return FALSE;<br />
<br />
regKey.SetValue(!bEnable, "Disable Performance Counters");<br />
regKey.Close();<br />
<br />
return TRUE;<br />
}<br />
<br />
<br />
int CMemoryUsage::GetMemoryUsage(DWORD dwProcessID)<br />
{<br />
if (m_bFirstTime)<br />
EnablePerformaceCounters();<br />
<br />
CPerfCounters< LONG > PerfCounters;<br />
<br />
DWORD dwObjectIndex = PROCESS_OBJECT_INDEX;<br />
DWORD dwMemoryUsageIndex = MEMORY_OBJECT_INDEX;<br />
<br />
LONG lnNewValue = 0;<br />
PPERF_DATA_BLOCK pPerfData = NULL;<br />
<br />
lnNewValue = PerfCounters.GetCounterValueForProcessID(&pPerfData, dwObjectIndex, dwMemoryUsageIndex, dwProcessID);<br />
<br />
return lnNewValue;<br />
}<br />
-- modified at 17:15 Tuesday 11th October, 2005
|
|
|
|
|
|
This code doesn't compile in Unicode, but it can be made to compile for Ansi and Unicode with a few simple changes.
Place _T() macros around all the strings. Change the "char" arrays to _TCHAR. Change strcpy to _tcscpy, and sprintf to _stprintf, and "{0}" to _T("") when initialising empty strings.
Separately the bstr compare on line 199 of perfcounters.h, seems very dubious to me. Using stricmp on a pair of bstr's (incorrectly casted to LPCTSTR), (I think) wouldn't ever compare more than the 1st character of the strings. You should be using "_wcsicmp" without the LPCTSTR cast. This applies to both Ansi and Uncode builds. Also, strictly, you shouldn't be using "!" since this isn't a boolean function. A compare against "== 0" would be "safer".
Regards
Jeremy
|
|
|
|
|
As for _bstr_t, i could use the == operator for the comparison.
However, casting LPCTSTR bstr_t class allocates new memory not in unicode format, and therefore the comparison will go through the whole string.
Furthermore, _bstr_t will delete the ansi memory in its destructor.
Dudi
|
|
|
|
|
Ok, I didn't know that about bstr's... guess one learns something new each day. However that still wouldn't be correct for a unicode compile since a TSTR is wide chars in Unicode, and you were doing a case-insensitive compare (which "==" isn't), so you would have to use a _tcsicmp.
Just to point out though, your code has saved me a huge amount of time, which is great. It just would be even better if you tweaked it for Unicode as well.
Jeremy.
|
|
|
|
|
I want to get the CpuUsage of all processes,so I storage ProcessID in a array.and i trandfer ProcessID to CCpuUsage::GetCpuUsage(DWORD dwProcessID).
But the CpuUsage of all processes is 100%.I wish that I will get your help!
thak you!
|
|
|
|
|
Which operation system do you use?
Did you try to debug it?
|
|
|
|
|
I use windows xp.The CpuUsage of all processes is 0% rather than 100%,I have debuged but not passed.I want to mail my project to you.Can you tell me your Email?
|
|
|
|
|
This is my code.I think that 0% result from LARGE_INTEGE NewPerfTime100nSec = {0}.I wish that get your more help!Can it get Cpuusage of all process if operation system is win98???
#include <windows.h>
#include <stdio.h>
#include "psapi.h"
#include "CpuUsage.h"
//Update Privilege of the specified process
BOOL UpdateProcessPrivilege( HANDLE hProcess, LPCTSTR lpPrivilegeName = SE_DEBUG_NAME )
{
HANDLE hToken;
if ( OpenProcessToken( hProcess, TOKEN_ALL_ACCESS, &hToken ) ) {
LUID destLuid;
if ( LookupPrivilegeValue( NULL, lpPrivilegeName, &destLuid ) ) {
TOKEN_PRIVILEGES TokenPrivileges;
TokenPrivileges.PrivilegeCount = 1;
TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
TokenPrivileges.Privileges[0].Luid = destLuid;
int iResult;
if ( iResult = AdjustTokenPrivileges( hToken, FALSE, &TokenPrivileges,
0, NULL, NULL ) ) {
return TRUE;
}
}
}
return FALSE;
}
// Print Information ofthe specified process
void PrintProcessInfo( DWORD processID )
{
HANDLE hProcess;
PROCESS_MEMORY_COUNTERS pmc;
DWORD cbNeeded;
HMODULE hModule = 0;
char path[MAX_PATH] = "";
char szName[MAX_PATH] = "";
CCpuUsage usage;
// print processID.
if (processID != 0)
{
printf( "%4u ", processID );
}
//Update Privilege of the specified process
UpdateProcessPrivilege( GetCurrentProcess(), SE_DEBUG_NAME );
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, processID );
if (NULL == hProcess)
return;
EnumProcessModules(hProcess, &hModule, sizeof(hModule), &cbNeeded);
GetModuleBaseName(hProcess, hModule, szName, sizeof(szName));
if (processID != 0)
{
if ((processID != 4) & (processID != 8))
{
printf(" %14s ",szName);
}
else
{
printf(" system ");
}
}
if ( GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc)) )
{
if (processID != 0)
{
printf( " %8d k", (pmc.WorkingSetSize )/1024);
}
}
//Print CpuUsage
int ProcessCpuUsageByID = usage.GetCpuUsage(processID);
if (processID != 0)
{
printf(" %8d%%", ProcessCpuUsageByID);
}
//Print process's path
GetModuleFileNameEx(hProcess, hModule, path, sizeof(path));
GetShortPathName(path,path,256);
if (processID != 0)
{
printf(" %s\n",path);
}
CloseHandle( hProcess );
CloseHandle(hModule);
}
void main( )
{
// Get processID
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
printf( "ProcessID PName Memory CpuUsage Path \n");
//while (true)
//{
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
return;
// Return ProcessNumber
cProcesses = cbNeeded / sizeof(DWORD);
// Print Process's information
for ( i = 0; i < cProcesses; i++ )
{
PrintProcessInfo( aProcesses[i] );
}
Sleep(1000);
//}
}
|
|
|
|
|
I have sent you my project.Can you answer this question?I am anxious that I get your help!Thank you !
|
|
|
|
|
Sorry for the delay.
I know what is wrong with your code.
In my article i wrote:
"Since the CPU usage can be determined by two samplings, the first call to GetCpuUsage() returns 0, and all calls thereafter returns the CPU usage" .
Now, your code takes the cpu usage only in one sampling for a process id. Thus, you get 0 for its cpu usage.
This is your code in the main function:
for ( i = 0; i < cProcesses; i++ )
{
PrintProcessInfo( aProcesses[i] );
}
PrintProcessInfo read the cpu usage only once for a process id and you need more than one sampling for getting the cpu usage.
My suggestion is to create an array of CCpuUsage, one for each process id, and to call the method GetCpuUsage after Sleep(1000) for each one.
If you have a problem let me know.
Dudi
|
|
|
|
|
Thanks a lot ! I have solved the question.I am glad to get your help! I am anxious that I have lots of chance to communicate with you!
|
|
|
|
|
On my WindowsXP machine, I got a cpu usage from "processID 0" to be higher than 100% although the system-wide cpu usage seems to be correct. Is it a bug? (I modified the output format and added a linefeed for debugging.)
SystemWide Explorer processID 0
========== ======== ===========
0% 0% 0%
5% 3% 189%
24% 17% 151%
2% 0% 196%
Canny
|
|
|
|
|
Well, i have XP with one processor and it displays the correct cpu usage of process 0 (which is "System Idle Process").
Do you have dual CPUs?
If you don't have then i don't know why you see more than 100% .
|
|
|
|
|
HI Dudi,
I have hyperthreading turned on, and the routine must have added all the percentages from all the "simulated" CPU's. So, do I divide the percentage by 2 or subtract it from 100? I think subtract by 100*(num_cpu-1).
Thank you very much for your response and a quick one too.
|
|
|
|
|
Thanks for the pgm.
Similarly How I can find Memory Usage by a specific process? Where can I find the index for memory usage similar to process index?
Thanks in Advance.
-Ganesh NV
Ganesh NV
Software Engineer.
Bangalore.
|
|
|
|
|
Well,
The process object has a counter, named "Virtual Bytes", whose index is 174.
Since the counter size is 4 bytes long, you need to change the declaration of "CPerfCounters<LONGLONG> PerfCounters;" to "CPerfCounters<LONG> PerfCounters;".
However, i don't know if that counter gives what you need.
|
|
|
|
|
I check in the performance counters and i found that the counter index is 180 which stands for "working set" in the performance counters.
It is 4 byte long therefore change the declaration CPerfCounters<LONGLONG> to CPerfCounters<LONG>.
The data is in bytes so don't forget to devide it by 1024 in order to display it in KB.
|
|
|
|
|
.. this was exactly what I needed for a distributed build app that uses idle cycles at our company for building data. Previously I could only get the CPU percentage of the task building the data, meaning that I might assign a task to a machine then find out it was only getting 1% CPU or something. I didn't know how to query when not doing a job since there was no suitable handle for 'nothing' to pass to GetProcessTimes(), only the handle when working on something.
This is great, all machines now report every second what CPU free they have *before* tasks are given out, and I count SETI@home (if found) to be idle cycles also.
|
|
|
|
|