I like to monitor the CPU utilization of a process like the Windows
Task Manager. My first approach was to query the system CPU times with
GetSystemTimes() and the process CPU times with GetProcessTimes() to
compute the CPU utilization of the process. This works fine if the
kernel load of the system is fairly low. If the kernel load is higher
it stops reporting accurate values: the utilization computed with
GetProcessTimes / GetSystemTimes is consistently lower then the
percentage reported by the Windows Task Manager.
Process Explorer reports the same values as GetProcessTimes /
GetSystemTimes (also lower than the Windows Task Manager) however it
was helpful to understand where the system spent the missing time:
Sysinternals Process Explorer shows the difference between the process
utilization reported by the Task Manager and GetProcessTimes /
GetSystemTimes in DPCs (deferred procedure calls).
So the Windows Task Manager knows which portion of the utilization
caused by DPCs belongs to a particular process. Process Explorer only
reports the overall time spent on DPCs and I don't know how to get
this information at all :-)
Could anybody please help me and point me in the right direction?
Thanks a lot,
Florian
http://msdn.microsoft.com/en-us/library/aa645516(VS.71).aspx
--
Phil Wilson
The Definitive Guide to Windows Installer
http://www.apress.com/book/view/1590592972
"Florian" <myste...@gmail.com> wrote in message
news:d0db2dba-e0d0-4d19...@x1g2000prb.googlegroups.com...
"Wilson, Phil" <ph...@wonderware.nospam.com> wrote in message
news:4445C003-EE6A-408C...@microsoft.com...
If you want the CPU utilization and DPC counters, why don't you use
the Performance Counter (PDH) API? Is this the help you are seeking?
I don't see anything in the performance counters that offers a % DPC
for the process itself. I see DPC related counters per CPU and total.
For example (dual core XP):
\\HDEV21\Processor(0)\% DPC Time
\\HDEV21\Processor(1)\% DPC Time
\\HDEV21\Processor(_total)\% DPC Time
To use the PDH API, you basically construct the strings for the
counters and use PdhAddCounter() to add them, and then begin taken
snapshots for the counter values.
Here is a C/C++ class object and console app I quickly snap together
to monitor counters.
-------------------- CUT HERE ----------------------
// File: MonitorPDH.cpp
// Compile: CL MonitorPDH.cpp /W3 /GX /MD /D "_AFXDLL"
#include <stdio.h>
#include <afx.h>
#include <conio.h>
#include <pdh.h>
#pragma comment(lib,"pdh.lib")
//--------------------------------------------------------
// CMonitorPdh
//
// Simple Class to display performance counters
class CMonitorPdh {
public:
CMonitorPdh();
~CMonitorPdh();
public:
//------------------------------------------------------
// Add a counter, add the machine automatically if
// not provided.
//
int AddCounter(const char *szCounter);
//------------------------------------------------------
// Start sampling of counters using a frequency of
// dwSampleMS (default 1000 ms). The sampling stops
// when the CheckExit() virtual function returns TRUE
//
BOOL Start(const DWORD dwSampleMs = 1000);
//------------------------------------------------------
// Add counter strings from a text file
BOOL LoadFromFile(const char *pszFileName);
//------------------------------------------------------
// Clear the counter list
void Clear() { m_saCounters.RemoveAll(); }
//------------------------------------------------------
// Return total counters added
int Count() { return m_saCounters.GetSize(); }
//------------------------------------------------------
// Dump the added counters
//
void DumpCounters();
//------------------------------------------------------
// Get the last pdh status recorded
//
PDH_STATUS GetLastStatus() { return m_pdhStatus; }
public:
//------------------------------------------------------
// Virtual function to exit sampling. For console apps,
// use the keyboard. For a GUI, you can use a PeekMessage()
// with a message detect.
//
virtual BOOL CheckExit();
protected:
BOOL OpenQuery();
BOOL CloseQuery();
BOOL FreeCounterHandles();
BOOL AllocateCounterHandles();
private:
HQUERY m_hQuery;
HCOUNTER *m_hCounters;
PDH_STATUS m_pdhStatus;
CStringArray m_saCounters;
char m_szMach[MAX_PATH];
};
CMonitorPdh::CMonitorPdh()
: m_hQuery(NULL), m_hCounters(NULL), m_pdhStatus(ERROR_SUCCESS)
{
m_szMach[0] = 0;
DWORD dw = sizeof(m_szMach)-1;
GetComputerName(m_szMach,&dw);
}
CMonitorPdh::~CMonitorPdh()
{
FreeCounterHandles();
CloseQuery();
}
BOOL CMonitorPdh::FreeCounterHandles()
{
if (m_hCounters) {
GlobalFree(m_hCounters);
m_hCounters = NULL;
}
return TRUE;
}
BOOL CMonitorPdh::AllocateCounterHandles()
{
FreeCounterHandles();
DWORD nTotal = m_saCounters.GetSize();
if (nTotal == 0) return FALSE;
m_hCounters = (HCOUNTER *)GlobalAlloc(GPTR, nTotal*sizeof(HCOUNTER));
return m_hCounters != NULL;
}
BOOL CMonitorPdh::OpenQuery()
{
if (!CloseQuery()) return FALSE;
m_pdhStatus = PdhOpenQuery (0, 0, &m_hQuery);
return m_pdhStatus == ERROR_SUCCESS;
}
BOOL CMonitorPdh::CloseQuery()
{
if (m_hQuery != NULL) {
m_pdhStatus = PdhCloseQuery(m_hQuery);
return m_pdhStatus == ERROR_SUCCESS;
}
return TRUE;
}
int CMonitorPdh::AddCounter(const char *szCounter)
{
CString s = szCounter;
if (s.Left(2) != "\\\\") {
s.Format("\\\\%s\\%s",m_szMach,szCounter);
}
int i = m_saCounters.Add(s);
return i;
}
void CMonitorPdh::DumpCounters()
{
DWORD nTotal = m_saCounters.GetSize();
for (DWORD i=0; i < nTotal; i++) {
printf("%04d: | %s\n",i,m_saCounters[i]);
}
}
// virtual
BOOL CMonitorPdh::CheckExit()
{
return _kbhit() && (getch() == 27);
}
BOOL CMonitorPdh::Start(const DWORD dwSampleMs /* = 1000 */)
{
if (!OpenQuery()) {
return FALSE;
}
if (!AllocateCounterHandles()) {
return FALSE;
}
DWORD nTotal = Count();
for (DWORD i=0; i < nTotal; i++) {
m_pdhStatus = PdhAddCounter (m_hQuery,
m_saCounters[i],
0,
m_hCounters + i*sizeof(HCOUNTER));
if (m_pdhStatus != ERROR_SUCCESS) {
return FALSE;
}
}
PDH_FMT_COUNTERVALUE fmtValue;
DWORD ctrType;
SYSTEMTIME stSampleTime;
CString sout;
//
// "Prime" counters
//
m_pdhStatus = PdhCollectQueryData (m_hQuery);
// Print counter values until a ESCAPE is pressed.
while (!CheckExit()) {
// Wait one interval.
Sleep(dwSampleMs);
//
// Get the sample time.
//
GetLocalTime (&stSampleTime);
//
// Get the current data values.
//
m_pdhStatus = PdhCollectQueryData (m_hQuery);
//
// Print the time stamp for the sampling.
//
sout.Format("\n\"%2.2d/%2.2d/%4.4d %2.2d:%2.2d:%2.2d.%3.3d\"",
stSampleTime.wMonth,
stSampleTime.wDay,
stSampleTime.wYear,
stSampleTime.wHour,
stSampleTime.wMinute,
stSampleTime.wSecond,
stSampleTime.wMilliseconds);
_tprintf(sout);
//
// Get the current counter values.
//
for (DWORD i = 0; i < nTotal; i++) {
m_pdhStatus = PdhGetFormattedCounterValue(
*(m_hCounters + i*sizeof(HCOUNTER)),
PDH_FMT_DOUBLE,
&ctrType,
&fmtValue);
if (m_pdhStatus == ERROR_SUCCESS) {
sout.Format("%.20g", fmtValue.doubleValue);
} else {
sout = "-1";
}
_tprintf(TEXT(",\"%s\""),sout);
}
}
_tprintf(TEXT("\n"));
FreeCounterHandles();
CloseQuery();
return TRUE;
}
BOOL CMonitorPdh::LoadFromFile(const char *pszFileName)
{
if (!pszFileName || !pszFileName[0]) {
SetLastError(ERROR_BAD_PATHNAME);
return FALSE;
}
CStdioFile f;
if (!f.Open(pszFileName, CFile::modeRead | CFile::typeText)) {
return FALSE;
}
Clear();
CString s;
while (f.ReadString(s)) {
s.TrimLeft(); s.TrimRight();
// skip blank and comment lines
if (s == "") continue;
if (s.FindOneOf(";#") == 0) continue;
// special command to end/stop loading
if (!stricmp(s,"stop")) break;
AddCounter(s);
}
f.Close();
return TRUE;
}
void main(char argc, char *argv[])
{
CMonitorPdh pdh;
// load string counters from text file
pdh.LoadFromFile("monitorpdh.txt");
// manually add counters
pdh.AddCounter("Process(wcserver)\\% Processor Time");
pdh.AddCounter("Process(wconline)\\% Processor Time");
pdh.AddCounter("Processor(1)\\% DPC Time");
// display counters
pdh.DumpCounters();
// begin sampling with a 250ms sampling rate, press
// ESCAPE to exit
pdh.Start(250);
}
-------------------- CUT HERE ----------------------
Hope this helps
--
HLS
Florian wrote:
--
HLS
http://msdn.microsoft.com/en-us/library/aa372183%28VS.85%29.aspx
I would like to do the monitoring for users with standard or even
limited access rights. I wonder if anything can be done to address
this problem?
-Florian
Florian wrote:
--
HLS