windows平台进程CPU占用率的计算

在进程的性能数据采集过程中,经常用到的一个性能指标就是进程的cpu占用率,下面给出它的计算方法及示例代码。

1、CPU占用率的定义

CPU占用率:指进程在一个时间段内消耗的CPU时间与该时间段长度的比值。

 

2、CPU占用率计算方法

根据上述定义,可以得到进程CPU占用率计算公式如下:

进程消耗的CPU时间 = 进程消耗的内核态时间 + 进程消耗的用户态时间,即 costTime = kernelTime + UserTime

进程的CPU占用率 = 进程消耗的CPU时间 / 刷新周期

 

3、CPU占用率计算涉及到的API

示例程序用到的主要API

GetSystemInfo    我们主要用它来获取系统中CPU核心个数

OpenProcess     用来打开指定进程的句柄

GetProcessTimes   根据OpenProcess返回的句柄,获取进程的KernelTime和UserTime

其它API(用于线程等其它情况下的计算)

OpenThread      获取指定线程的句柄

GetThreadTimes    根据OpenThread返回的句柄,获取线程的KernelTime和UserTime (可用于线程CPU占用率计算)

GetSystemTimes   获取总的CPU时间IdleTime KernelTime UserTime,可用于系统总的CPU占用率计算(注:多核CPU中返回的是所有CPU核时间的总和)

NtQuerySystemInformation  这是个native api,可以获取到许多信息

 

4、示例代码

  1 #include "stdafx.h"
  2 #include <conio.h>
  3 #include <windows.h>
  4 #include <TlHelp32.h>
  5 #include <process.h>
  6 
  7 #define MY_PROCESS_ERROR(Condition) do{ if (!(Condition))  goto Exit0; } while (false)
  8 
  9 static DWORD g_sdwTickCountOld = 0;                // 上一次的tick计数
 10 static LARGE_INTEGER g_slgProcessTimeOld;        // 保存进程上一次的时间占用
 11 static DWORD g_sdwProcessorCoreNum = 0;            // 处理器核心数
 12 static HANDLE g_shExitEvent = NULL;                // 线程退出控制
 13 
 14 typedef struct _TARGET_PROCESS
 15 {
 16     DWORD        dwProcessId;                    // 进程ID
 17 }TARGET_PROCESS, *PTARGET_PROCESS;
 18 
 19 
 20 
 21 /*@brief 获取找到的与指定进程名相符的第一个进程ID
 22 * @param [in]        cpszExeFileName        进程可执行文件名(不带路径)
 23 * @param [in/out]    dwPID                返回找到的名字符合的第一个进程ID
 24 * @return 成功 : S_OK    失败 : 错误码
 25 */
 26 HRESULT FindFirstProcessIdByName(const TCHAR* cpszExeFileName, DWORD &dwPID)
 27 {
 28     HRESULT hr = E_FAIL;
 29 
 30     PROCESSENTRY32 pe = { 0 };
 31     HANDLE hSnapshot = NULL;
 32 
 33     if (NULL == cpszExeFileName)
 34     {
 35         hr = HRESULT_FROM_WIN32(ERROR_BAD_ARGUMENTS);
 36         goto Exit0;
 37     }
 38 
 39     pe.dwSize = sizeof(PROCESSENTRY32);
 40     hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
 41     if (INVALID_HANDLE_VALUE == hSnapshot)
 42     {
 43         hr = HRESULT_FROM_WIN32(GetLastError());
 44         goto Exit0;
 45     }  
 46 
 47     if (FALSE == Process32First(hSnapshot, &pe))
 48     {
 49         hr = HRESULT_FROM_WIN32(ERROR_NO_MORE_FILES);
 50         goto Exit0;
 51     }
 52 
 53     hr = S_FALSE;
 54     do
 55     {
 56         if (0 == _tcsicmp(cpszExeFileName, pe.szExeFile))
 57         {
 58             dwPID = pe.th32ProcessID;
 59             hr = S_OK;
 60             break;
 61         }
 62     }while(Process32Next(hSnapshot, &pe));
 63 
 64 Exit0:
 65     if(hSnapshot)
 66     {
 67         CloseHandle(hSnapshot);
 68         hSnapshot = NULL;
 69     }
 70 
 71     return hr;
 72 }
 73 
 74 /*@brief 获取进程的Cpu占用率
 75 * @param [in]    hProcess            进程句柄
 76 * @param [in]    dwElepsedTime        取样间隔时间(毫秒)
 77 * @return 成功 : cpu占用率    失败 : -1
 78 */
 79 int GetProcessCpuPercent(const HANDLE hProcess, const DWORD dwElepsedTime)
 80 {
 81     int nProcCpuPercent = 0;
 82     BOOL bRetCode = FALSE;
 83 
 84     FILETIME CreateTime, ExitTime, KernelTime,UserTime;
 85     LARGE_INTEGER lgKernelTime;
 86     LARGE_INTEGER lgUserTime;
 87     LARGE_INTEGER lgCurTime;
 88 
 89     bRetCode = GetProcessTimes(hProcess, &CreateTime, &ExitTime, &KernelTime, &UserTime);
 90     if (bRetCode)
 91     {
 92         lgKernelTime.HighPart = KernelTime.dwHighDateTime;
 93         lgKernelTime.LowPart = KernelTime.dwLowDateTime;
 94 
 95         lgUserTime.HighPart = UserTime.dwHighDateTime;
 96         lgUserTime.LowPart = UserTime.dwLowDateTime;
 97 
 98         lgCurTime.QuadPart = (lgKernelTime.QuadPart + lgUserTime.QuadPart) / 10000;
 99         nProcCpuPercent = (int)((lgCurTime.QuadPart - g_slgProcessTimeOld.QuadPart) * 100 / dwElepsedTime);
100         g_slgProcessTimeOld = lgCurTime;
101         nProcCpuPercent = nProcCpuPercent / g_sdwProcessorCoreNum;
102     }
103     else
104     {
105         nProcCpuPercent = -1;
106     }
107 
108     return nProcCpuPercent;
109 }
110 
111 unsigned __stdcall WorkerThread(void *pArg)
112 {
113     HRESULT hr = E_FAIL;
114 
115     HANDLE hProcess = NULL;
116     DWORD dwProcessId = 0;
117     DWORD dwRetVal = 0;
118     DWORD dwCurrentTickCount = 0;
119     DWORD dwElapsedTime = 0;
120     int nProcessCpuPercent = 0;
121     
122     TARGET_PROCESS *pTargetProcess = (TARGET_PROCESS *)pArg;
123 
124     dwProcessId = pTargetProcess->dwProcessId;
125     hProcess = OpenProcess(PROCESS_QUERY_INFORMATION , FALSE, dwProcessId);
126     MY_PROCESS_ERROR(hProcess);
127 
128     do 
129     {
130         dwRetVal = WaitForSingleObject(g_shExitEvent, 1000);
131         if (WAIT_OBJECT_0 == dwRetVal ||
132             WAIT_FAILED == dwRetVal
133             )
134         {
135             break;
136         }
137 
138         dwCurrentTickCount = GetTickCount();
139         dwElapsedTime = dwCurrentTickCount - g_sdwTickCountOld;
140         g_sdwTickCountOld = dwCurrentTickCount;
141         nProcessCpuPercent = GetProcessCpuPercent(hProcess, dwElapsedTime);
142         wprintf(L"cpu = %d\n", nProcessCpuPercent);
143     } while (1);    
144 Exit0:
145     if (hProcess)
146     {
147         CloseHandle(hProcess);
148         hProcess = NULL;
149     }
150     
151     return 0;
152 }
153 
154 int _tmain(int argc, _TCHAR* argv[])
155 {
156     HRESULT hr = E_FAIL;
157     
158     HANDLE hThread = NULL;
159     unsigned int uiTid = 0;
160     SYSTEM_INFO sysInfo = { 0 };
161     TARGET_PROCESS struTargetProcess;
162 
163     if (argc > 1)
164     {
165         hr = FindFirstProcessIdByName(argv[1], struTargetProcess.dwProcessId);
166         if (S_OK != hr)
167         {
168             _tprintf(_T("Can't find process \'%s\' ret=0x%X\n"), argv[1], hr);
169             goto Exit0;
170         }
171 
172         GetSystemInfo(&sysInfo);
173         g_sdwProcessorCoreNum = sysInfo.dwNumberOfProcessors;
174 
175         g_shExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
176         MY_PROCESS_ERROR(g_shExitEvent);
177 
178         hThread = (HANDLE)_beginthreadex(NULL, 0, WorkerThread, &struTargetProcess, 0, &uiTid);
179         MY_PROCESS_ERROR(hThread);
180 
181         _getch();
182         SetEvent(g_shExitEvent);
183         WaitForSingleObject(hThread, INFINITE);
184     }
185     else
186     {
187         _tprintf(_T("Please input a process name.\n"));
188     }
189 
190 Exit0:
191     if (hThread)
192     {
193         CloseHandle(hThread);
194         hThread = NULL;
195     }
196 
197     if (g_shExitEvent)
198     {
199         CloseHandle(g_shExitEvent);
200         g_shExitEvent = NULL;
201     }
202 
203     return 0;
204 }

 

 

 

posted @ 2012-06-28 14:00  宇月--测试开发梦想家  阅读(11095)  评论(1编辑  收藏  举报