CPU Auslastung auslesen



  • meine lösung leuft auch nur auf NT-System(w2k,wxp getestet).
    wolt ihr sie denoch haben??

    MFG TaccoGo



  • Klar wollen wir, und wenn es gut ist kann mann es in einem seperaten Thread stecken und in die FAQ schieben.



  • @flenders

    HKEY_DYNAMIC_DATA benutze ich bei mir (w98se), ich hatte mal vor ewigkeiten ein tut in VB drüber gelesen und es in C++ umgesetzt, nur bin ich mir sicher das es auch anders geht, den Windows muß diesen Wert auch ermitteln und in die Reg schreiben.



  • Klar muss auch Windows diesen Wert irgendwie ermitteln, aber das heißt deswegen noch lange nicht, dass du noch anders an diesen Wert kommst. Es kann natürlich sein, dass es noch eine Möglichkeit gibt, aber Windows kümmert sich eben und die Zuteilung der Rechenzeit, und weiß von daher, wieviel Rechenzeit der Windows-Leerlauf-Prozess bekommt (denke mal, dass das irgendwie so ermittelt wird)



  • @MiC++ha

    Wegen der Unterstützung für 98, Me ... Systeme: Hat Ms den Task Manager zu NT Systemen nicht gründlich geändert. Wenn ich mich richtig erinnere, gab es damals solche Systeminfos Systemauslastung nicht im Taskmanager. (Da gabs auch noch bugs das nicht alle Programme aufgeführt wurden, spielte bei Viren mal ne Rolle).

    -> Wenn Ms es damals nicht den Taskmanager eingebaut hat, war es entweder zu blöd dazu (besser hat es vergessen) oder es war zu schwirig diese Werte zu ermitteln.

    Was wohl möglich ist ist die Ramauslastung rauszukriegen (IMHO), aber das ist ja nicht die Systemauslastung.



  • Ich habe mich ein wenig Schlau gemacht, aber noch nicht Schlau genug um Endergebnisse zu liefern, aber so wie es Aussieht muß man das ziemlich hardware nah machen, sprich Assembler (Eingebettet) aber auch da giebt es noch Hürden.

    Also für mich selbst reicht meine alte variante, ich brauch nicht von jeden die Auslastung.



  • Hallo,

    also gundlegend habe ich das so gemacht:

    int CPU=0;
    FILETIME ct,et,kt,ut;
    GetProcessTimes(h_proc,&ct,&et,&kt,&ut);
    double n,m,nSeks=10000;
    static int nTime[100];
    m=nSeks*1000;
    n=kt.dwLowDateTime-nTime[i];
    if (n>m)
    	n=m;
    CPU=int((n/m)*100);
    nTime=kt.dwLowDateTime;
    

    int CPU ist die auslastung in %.
    aller dings muss das ständig widerhold werden.

    achso h_proc ist das handle auf den prozess den man über wacht.

    MFG TaccoGo



  • Hallo nochmal,

    ich habe meine rescherschen von damals nochmal durchgegangen und habe fest gestelt das ich speter noch code gefunden habe der richtig gut ist.

    den habe ich irgendwo gefunden wies aber nichtmer wo:

    die header-datei

    //#include <windows.h>
    #include <comdef.h>	// for using bstr_t class
    
    #define TOTALBYTES    100*1024
    #define BYTEINCREMENT 1024
    
    template <class T>
    class CPerfCounters
    {
    public:
    	CPerfCounters()
    	{
    	}
    	~CPerfCounters()
    	{
    	}
    
    	T GetCounterValue(PERF_DATA_BLOCK **pPerfData, DWORD dwObjectIndex, DWORD dwCounterIndex, LPCTSTR pInstanceName = NULL)	
    	{
    		QueryPerformanceData(pPerfData);
    
    	    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)
    	{
    		//
    		// 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;
    
    		Buffer.Reset();
    		while( (lRes = RegQueryValueEx( HKEY_PERFORMANCE_DATA,
    								   "Global",
    								   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) );
    	}
    };
    

    und noch par funktionen

    ///////////////////////////////////////////////////////////////////
    //
    //		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 <atlbase.h>	// for CRegKey use
    
    #pragma pack(push,8)
    #include "PerfCounters.h"
    #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)
    
    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;
    }
    
    BOOL EnablePerformaceCounters(BOOL bEnable = TRUE)
    {
    	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();
    
    	return TRUE;
    }
    
    //
    //	GetCpuUsage returns the 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 GetCpuUsage()
    {
    	static bool bFirstTime = true;
    	static LONGLONG			lnOldValue = 0;
    	static LARGE_INTEGER	OldPerfTime100nSec = {0};
    	static PLATFORM Platform = GetPlatform();
    
    	if (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 (bFirstTime)
    	{
    		bFirstTime = false;
    		lnOldValue = lnNewValue;
    		OldPerfTime100nSec = NewPerfTime100nSec;
    		return 0;
    	}
    
    	LONGLONG lnValueDelta = lnNewValue - lnOldValue;
    	double DeltaPerfTime100nSec = (double)NewPerfTime100nSec.QuadPart - (double)OldPerfTime100nSec.QuadPart;
    
    	lnOldValue = lnNewValue;
    	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 GetCpuUsage(LPCTSTR pProcessName)
    {
    	static bool bFirstTime = true;
    	static LONGLONG			lnOldValue = 0;
    	static LARGE_INTEGER	OldPerfTime100nSec = {0};
    	static PLATFORM Platform = GetPlatform();
    
    	if (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 (bFirstTime)
    	{
    		bFirstTime = false;
    		lnOldValue = lnNewValue;
    		OldPerfTime100nSec = NewPerfTime100nSec;
    		return 0;
    	}
    
    	LONGLONG lnValueDelta = lnNewValue - lnOldValue;
    	double DeltaPerfTime100nSec = (double)NewPerfTime100nSec.QuadPart - (double)OldPerfTime100nSec.QuadPart;
    
    	lnOldValue = lnNewValue;
    	OldPerfTime100nSec = NewPerfTime100nSec;
    
    	double a = (double)lnValueDelta / DeltaPerfTime100nSec;
    
    	CpuUsage = (int) (a*100);
    	if (CpuUsage < 0)
    		return 0;
    	return CpuUsage;
    }
    

    wen man das einbaut funktionrt das recht gut.

    MFG TaccoGo



  • cool. Danke! Das sollte wirklich in die FAQ.



  • Kann das nochmal jemand (der etwas davon versteht - deswegen mach ich es nicht 😉 ) testen und den Code durchgehen, bevor ich ihn in die FAQ stelle?!



  • Hallo,

    ich habe das bie mir getestend es stimt mit den Task-Manage überein, und der Allgoritmus ist im grunde so wie meiner.

    MFG TaccoGo


Anmelden zum Antworten