//.h
#ifndef _CPUUSAGE_H
#define _CPUUSAGE_H
#include <windows.h>
#include <WINPERF.H>
#include <comdef.h> // for using bstr_t class
#include <atlbase.h>
#include "stdafx.h"
#pragma pack(push,8)
#pragma pack(pop)
#define SYSTEM_OBJECT_INDEX 2 // 'System' object
#define PROCESS_OBJECT_INDEX 230 // 'Process' object
#define PROCESSOR_OBJECT_INDEX 238 // 'Processor' object
#define TOTAL_PROCESSOR_TIME_COUNTER_INDEX 240 // '% Total processor time' counter (valid in WinNT under 'System' object)
#define PROCESSOR_TIME_COUNTER_INDEX 6 // '% processor time' counter (for Win2K/XP)
#define TOTALBYTES 100*1024
#define BYTEINCREMENT 10*1024
class CCpuUsage
{
public:
CCpuUsage();
virtual ~CCpuUsage();
// Methods
int GetCpuUsage();
int GetCpuUsage(LPCTSTR pProcessName);
BOOL EnablePerformaceCounters(BOOL bEnable = TRUE);
// Attributes
private:
bool m_bFirstTime;
LONGLONG m_lnOldValue ;
LARGE_INTEGER m_OldPerfTime100nSec;
};
template <class T>
class CPerfCounters
{
public:
CPerfCounters()
{
}
~CPerfCounters()
{
}
T GetCounterValue(PERF_DATA_BLOCK **pPerfData, DWORD dwObjectIndex, DWORD dwCounterIndex, LPCTSTR pInstanceName = NULL)
{
QueryPerformanceData(pPerfData, dwObjectIndex, dwCounterIndex);
PPERF_OBJECT_TYPE pPerfObj = NULL;
T lnValue = {0};
// Get the first object type.
pPerfObj = FirstObject( *pPerfData );
// Look for the given object index
for( DWORD i=0; i<(*pPerfData)->NumObjectTypes; i++ )
{
if (pPerfObj->ObjectNameTitleIndex == dwObjectIndex)
{
lnValue = GetCounterValue(pPerfObj, dwCounterIndex, pInstanceName);
break;
}
pPerfObj = NextObject( pPerfObj );
}
return lnValue;
}
protected:
class CBuffer
{
public:
CBuffer(UINT Size)
{
m_Size = Size;
m_pBuffer = (LPBYTE) malloc( Size*sizeof(BYTE) );
}
~CBuffer()
{
free(m_pBuffer);
}
void *Realloc(UINT Size)
{
m_Size = Size;
m_pBuffer = (LPBYTE) realloc( m_pBuffer, Size );
return m_pBuffer;
}
void Reset()
{
memset(m_pBuffer,NULL,m_Size);
}
operator LPBYTE ()
{
return m_pBuffer;
}
UINT GetSize()
{
return m_Size;
}
public:
LPBYTE m_pBuffer;
private:
UINT m_Size;
};
//
// The performance data is accessed through the registry key
// HKEY_PEFORMANCE_DATA.
// However, although we use the registry to collect performance data,
// the data is not stored in the registry database.
// Instead, calling the registry functions with the HKEY_PEFORMANCE_DATA key
// causes the system to collect the data from the appropriate system
// object managers.
//
// QueryPerformanceData allocates memory block for getting the
// performance data.
//
//
void QueryPerformanceData(PERF_DATA_BLOCK **pPerfData, DWORD dwObjectIndex, DWORD dwCounterIndex)
{
//
// Since i want to use the same allocated area for each query,
// i declare CBuffer as static.
// The allocated is changed only when RegQueryValueEx return ERROR_MORE_DATA
//
static CBuffer Buffer(TOTALBYTES);
DWORD BufferSize = Buffer.GetSize();
LONG lRes;
char keyName[8];
sprintf(keyName,"%d %d",dwObjectIndex, dwCounterIndex);
Buffer.Reset();
while( (lRes = RegQueryValueEx( HKEY_PERFORMANCE_DATA,
keyName,
NULL,
NULL,
Buffer,
&BufferSize )) == ERROR_MORE_DATA )
{
// Get a buffer that is big enough.
BufferSize += BYTEINCREMENT;
Buffer.Realloc(BufferSize);
}
*pPerfData = (PPERF_DATA_BLOCK) Buffer.m_pBuffer;
}
//
// GetCounterValue gets performance object structure
// and returns the value of given counter index .
// This functions iterates through the counters of the input object
// structure and looks for the given counter index.
//
// For objects that have instances, this function returns the counter value
// of the instance pInstanceName.
//
T GetCounterValue(PPERF_OBJECT_TYPE pPerfObj, DWORD dwCounterIndex, LPCTSTR pInstanceName)
{
PPERF_COUNTER_DEFINITION pPerfCntr = NULL;
PPERF_INSTANCE_DEFINITION pPerfInst = NULL;
PPERF_COUNTER_BLOCK pCounterBlock = NULL;
// Get the first counter.
pPerfCntr = FirstCounter( pPerfObj );
// Look for the index of '% Total processor time'
for( DWORD j=0; j < pPerfObj->NumCounters; j++ )
{
if (pPerfCntr->CounterNameTitleIndex == dwCounterIndex)
break;
// Get the next counter.
pPerfCntr = NextCounter( pPerfCntr );
}
if( pPerfObj->NumInstances == PERF_NO_INSTANCES )
{
pCounterBlock = (PPERF_COUNTER_BLOCK) ((LPBYTE) pPerfObj + pPerfObj->DefinitionLength);
}
else
{
pPerfInst = FirstInstance( pPerfObj );
// Look for instance pInstanceName
_bstr_t bstrInstance;
_bstr_t bstrInputInstance = pInstanceName;
for( int k=0; k< pPerfObj->NumInstances; k++ )
{
bstrInstance = (wchar_t *)((PBYTE)pPerfInst + pPerfInst->NameOffset);
if (!stricmp((LPCTSTR)bstrInstance, (LPCTSTR)bstrInputInstance))
{
pCounterBlock = (PPERF_COUNTER_BLOCK) ((LPBYTE) pPerfInst + pPerfInst->ByteLength);
break;
}
// Get the next instance.
pPerfInst = NextInstance( pPerfInst );
}
}
if (pCounterBlock)
{
T *lnValue = NULL;
lnValue = (T*)((LPBYTE) pCounterBlock + pPerfCntr->CounterOffset);
return *lnValue;
}
return -1;
}
/*****************************************************************
* *
* Functions used to navigate through the performance data. *
* *
*****************************************************************/
PPERF_OBJECT_TYPE FirstObject( PPERF_DATA_BLOCK PerfData )
{
return( (PPERF_OBJECT_TYPE)((PBYTE)PerfData + PerfData->HeaderLength) );
}
PPERF_OBJECT_TYPE NextObject( PPERF_OBJECT_TYPE PerfObj )
{
return( (PPERF_OBJECT_TYPE)((PBYTE)PerfObj + PerfObj->TotalByteLength) );
}
PPERF_COUNTER_DEFINITION FirstCounter( PPERF_OBJECT_TYPE PerfObj )
{
return( (PPERF_COUNTER_DEFINITION) ((PBYTE)PerfObj + PerfObj->HeaderLength) );
}
PPERF_COUNTER_DEFINITION NextCounter( PPERF_COUNTER_DEFINITION PerfCntr )
{
return( (PPERF_COUNTER_DEFINITION)((PBYTE)PerfCntr + PerfCntr->ByteLength) );
}
PPERF_INSTANCE_DEFINITION FirstInstance( PPERF_OBJECT_TYPE PerfObj )
{
return( (PPERF_INSTANCE_DEFINITION)((PBYTE)PerfObj + PerfObj->DefinitionLength) );
}
PPERF_INSTANCE_DEFINITION NextInstance( PPERF_INSTANCE_DEFINITION PerfInst )
{
PPERF_COUNTER_BLOCK PerfCntrBlk;
PerfCntrBlk = (PPERF_COUNTER_BLOCK)((PBYTE)PerfInst + PerfInst->ByteLength);
return( (PPERF_INSTANCE_DEFINITION)((PBYTE)PerfCntrBlk + PerfCntrBlk->ByteLength) );
}
};
#endif
//.cpp
///////////////////////////////////////////////////////////////////
//
// GetCpuUsage uses the performance counters to retrieve the
// system cpu usage.
// The cpu usage counter is of type PERF_100NSEC_TIMER_INV
// which as the following calculation:
//
// Element Value
// ======= ===========
// X CounterData
// Y 100NsTime
// Data Size 8 Bytes
// Time base 100Ns
// Calculation 100*(1-(X1-X0)/(Y1-Y0))
//
// where the denominator (Y) represents the total elapsed time of the
// sample interval and the numerator (X) represents the time during
// the interval when the monitored components were inactive.
//
//
// Note:
// ====
// On windows NT, cpu usage counter is '% Total processor time'
// under 'System' object. However, in Win2K/XP Microsoft moved
// that counter to '% processor time' under '_Total' instance
// of 'Processor' object.
// Read 'INFO: Percent Total Performance Counter Changes on Windows 2000'
// Q259390 in MSDN.
//
///////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "cpu.h"
typedef enum
{
WINNT, WIN2K_XP, WIN9X, UNKNOWN
}PLATFORM;
PLATFORM GetPlatform()
{
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (!GetVersionEx(&osvi))
return UNKNOWN;
switch (osvi.dwPlatformId)
{
case VER_PLATFORM_WIN32_WINDOWS:
return WIN9X;
case VER_PLATFORM_WIN32_NT:
if (osvi.dwMajorVersion == 4)
return WINNT;
else
return WIN2K_XP;
}
return UNKNOWN;
}
CCpuUsage::CCpuUsage()
{
m_bFirstTime = true;
m_lnOldValue = 0;
memset(&m_OldPerfTime100nSec, 0, sizeof(m_OldPerfTime100nSec));
}
CCpuUsage::~CCpuUsage()
{
}
BOOL CCpuUsage::EnablePerformaceCounters(BOOL bEnable)
{
if (GetPlatform() != WIN2K_XP)
return TRUE;
CRegKey regKey;
if (regKey.Open(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\PerfOS\\Performance") != ERROR_SUCCESS)
return FALSE;
regKey.SetValue(!bEnable, "Disable Performance Counters");
regKey.Close();
if (regKey.Open(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\PerfProc\\Performance") != ERROR_SUCCESS)
return FALSE;
regKey.SetValue(!bEnable, "Disable Performance Counters");
regKey.Close();
return TRUE;
}
//
// GetCpuUsage returns the system-wide cpu usage.
// Since we calculate the cpu usage by two samplings, the first
// call to GetCpuUsage() returns 0 and keeps the values for the next
// sampling.
// Read the comment at the beginning of this file for the formula.
//
int CCpuUsage::GetCpuUsage()
{
static PLATFORM Platform = GetPlatform();
if (m_bFirstTime)
EnablePerformaceCounters();
// Cpu usage counter is 8 byte length.
CPerfCounters<LONGLONG> PerfCounters;
char szInstance[256] = {0};
// Note:
// ====
// On windows NT, cpu usage counter is '% Total processor time'
// under 'System' object. However, in Win2K/XP Microsoft moved
// that counter to '% processor time' under '_Total' instance
// of 'Processor' object.
// Read 'INFO: Percent Total Performance Counter Changes on Windows 2000'
// Q259390 in MSDN.
DWORD dwObjectIndex;
DWORD dwCpuUsageIndex;
switch (Platform)
{
case WINNT:
dwObjectIndex = SYSTEM_OBJECT_INDEX;
dwCpuUsageIndex = TOTAL_PROCESSOR_TIME_COUNTER_INDEX;
break;
case WIN2K_XP:
dwObjectIndex = PROCESSOR_OBJECT_INDEX;
dwCpuUsageIndex = PROCESSOR_TIME_COUNTER_INDEX;
strcpy(szInstance,"_Total");
break;
default:
return -1;
}
int CpuUsage = 0;
LONGLONG lnNewValue = 0;
PPERF_DATA_BLOCK pPerfData = NULL;
LARGE_INTEGER NewPerfTime100nSec = {0};
lnNewValue = PerfCounters.GetCounterValue(&pPerfData, dwObjectIndex, dwCpuUsageIndex, szInstance);
NewPerfTime100nSec = pPerfData->PerfTime100nSec;
if (m_bFirstTime)
{
m_bFirstTime = false;
m_lnOldValue = lnNewValue;
m_OldPerfTime100nSec = NewPerfTime100nSec;
return 0;
}
LONGLONG lnValueDelta = lnNewValue - m_lnOldValue;
double DeltaPerfTime100nSec = (double)NewPerfTime100nSec.QuadPart - (double)m_OldPerfTime100nSec.QuadPart;
m_lnOldValue = lnNewValue;
m_OldPerfTime100nSec = NewPerfTime100nSec;
double a = (double)lnValueDelta / DeltaPerfTime100nSec;
double f = (1.0 - a) * 100.0;
CpuUsage = (int)(f + 0.5); // rounding the result
if (CpuUsage == 0)
return 0;
return CpuUsage;
}
int CCpuUsage::GetCpuUsage(LPCTSTR pProcessName)
{
static PLATFORM Platform = GetPlatform();
if (m_bFirstTime)
EnablePerformaceCounters();
// Cpu usage counter is 8 byte length.
CPerfCounters<LONGLONG> PerfCounters;
char szInstance[256] = {0};
DWORD dwObjectIndex = PROCESS_OBJECT_INDEX;
DWORD dwCpuUsageIndex = PROCESSOR_TIME_COUNTER_INDEX;
strcpy(szInstance,pProcessName);
int CpuUsage = 0;
LONGLONG lnNewValue = 0;
PPERF_DATA_BLOCK pPerfData = NULL;
LARGE_INTEGER NewPerfTime100nSec = {0};
lnNewValue = PerfCounters.GetCounterValue(&pPerfData, dwObjectIndex, dwCpuUsageIndex, szInstance);
NewPerfTime100nSec = pPerfData->PerfTime100nSec;
if (m_bFirstTime)
{
m_bFirstTime = false;
m_lnOldValue = lnNewValue;
m_OldPerfTime100nSec = NewPerfTime100nSec;
return 0;
}
LONGLONG lnValueDelta = lnNewValue - m_lnOldValue;
double DeltaPerfTime100nSec = (double)NewPerfTime100nSec.QuadPart - (double)m_OldPerfTime100nSec.QuadPart;
m_lnOldValue = lnNewValue;
m_OldPerfTime100nSec = NewPerfTime100nSec;
double a = (double)lnValueDelta / DeltaPerfTime100nSec;
CpuUsage = (int) (a*100);
if (CpuUsage == 0)
return 0;
return CpuUsage;
}
計算CPU的方法
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.