在函数 GetIdleTime 的用法中,MSDN 推荐的 CPU 使用率的计算方法,在部分平台下使用时得到的使用率异常:非 0-100% 的数值。
先看看 MSDN 推荐的算法的大概实现:
1 static void CallCountCpuIdleThread(CCountCpuDlg *pCCountCpuDlg) 2 { 3 DWORD dwStartTick; 4 DWORD dwIdleStart; 5 DWORD dwStopTick; 6 DWORD dwIdleEnd; 7 int nPresentIdle; 8 int nCpuUage[10]={0}; 9 int nCount=0; 10 int ave=0; 11 DWORD sum=0; 12 int i; 13 14 while(1) 15 { 16 dwStartTick=GetTickCount(); // 此处为关键代码 Leo.Zheng 17 dwIdleStart=GetIdleTime(); 18 Sleep(100); 19 dwStopTick=GetTickCount(); 20 dwIdleEnd=GetIdleTime(); 21 22 nPresentIdle=(100*(dwIdleEnd-dwIdleStart))/((dwStopTick-dwStartTick)); 23 // 算法多次的一个平均值 Leo.Zheng 24 if(nCount<10) 25 { 26 nCpuUage[nCount]=nPresentIdle; 27 nCount++; 28 if(nCount==10) 29 { 30 for(i=0;i<10;i++) 31 sum+=nCpuUage[i]; 32 ave=sum/10; 33 // g_nCpuIdle only read in the main thread 34 g_nCpuIdle=ave; 35 nCount=0; 36 sum=0; 37 //RETAILMSG(1,(TEXT("CPU laoding is %d /r/n"),ave)); 38 } 39 } 40 } 41 }
不使用 GetIdleTime 的计算 CPU 使用率的方法及调用示例如下:
1 /* 2 // 调用示例 3 DWORD dwThreadID = 0; 4 HANDLE hThread = NULL; 5 hThread = CreateThread(NULL,0,ThreadPrintCpuLoad,this,0,&dwThreadID); 6 if(NULL != hThread) 7 { 8 CloseHandle(hThread); 9 } 10 */ 11 static DWORD GetThreadTick(FILETIME *pFtKernel, FILETIME *pFtUser) 12 { 13 __int64 iKernel64 = 0; 14 __int64 iUser64 = 0; 15 16 iKernel64 = pFtKernel->dwHighDateTime; 17 iKernel64 <<= 32; 18 iKernel64 += pFtKernel->dwLowDateTime; 19 20 iUser64 = pFtUser->dwHighDateTime; 21 iUser64 <<= 32; 22 iKernel64 += pFtUser->dwLowDateTime; 23 24 iKernel64 += iUser64; 25 26 // nano sec to milli sec 27 iKernel64 /= 10000; 28 29 return (DWORD)iKernel64; 30 } 31 32 static void IdleThread(LPVOID pvParams) 33 { 34 while(1) 35 { 36 } 37 } 38 39 static DWORD ThreadPrintCpuLoad(LPVOID lpParameter) 40 { 41 DWORD dwThreadID = 0; 42 HANDLE hIdleThread = NULL; 43 44 SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_HIGHEST); // 设置高的优先级,保证 CPU 忙的时候也能打印 Leo 45 46 hIdleThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)IdleThread,NULL,CREATE_SUSPENDED,&dwThreadID); // 创建低优先级空闲线程 Leo.Zheng 47 SetThreadPriority(hIdleThread,THREAD_PRIORITY_IDLE); 48 ResumeThread(hIdleThread); 49 50 while(1) 51 { 52 Sleep(1000); // 1S打印一次 Leo.Zheng 53 54 static DWORD dwLastThreadTime = 0; 55 static DWORD dwLastTickTime = 0; 56 DWORD dwCurrentThreadTime = 0; 57 DWORD dwCurrentTickTime = 0; 58 DWORD dwCpuPower = 0; 59 60 FILETIME ftCreationTime; 61 FILETIME ftExitTime; 62 FILETIME ftKernelTime; 63 FILETIME ftUserTime; 64 65 SuspendThread(hIdleThread); 66 67 dwCurrentTickTime = GetTickCount(); 68 GetThreadTimes(hIdleThread,&ftCreationTime,&ftExitTime,&ftKernelTime,&ftUserTime); 69 dwCurrentThreadTime = GetThreadTick(&ftKernelTime,&ftUserTime); 70 71 // 计算 CPU 占用率 72 if(dwCurrentTickTime != dwLastTickTime || 0 != dwLastThreadTime || 0 != dwLastTickTime) 73 { 74 dwCpuPower = 100 - (((dwCurrentThreadTime - dwLastThreadTime) * 100) / (dwCurrentTickTime - dwLastTickTime)); 75 } 76 else 77 { 78 dwCpuPower = 0; 79 } 80 81 // save status 82 dwLastTickTime = GetTickCount(); 83 dwLastThreadTime = dwCurrentThreadTime; 84 85 printf("CPU loaded: %d%% ",dwCpuPower); 86 87 ResumeThread(hIdleThread); 88 } 89 }