計算CPU的方法

//.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;   
}   



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章