在进程的性能数据采集过程中,经常用到的一个性能指标就是进程的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 }



所有评论(0)