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

来源:互联网 发布:淘宝酒仙网 编辑:程序博客网 时间:2024/05/17 06:40

在进程的性能数据采集过程中,经常用到的一个性能指标就是进程的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,可以获取到许多信息。可以获得更细致的CPU使用率信息。(如每个核心的使用率)

 

4、示例代码

#include "stdafx.h"#include <conio.h>#include <windows.h>#include <TlHelp32.h>#include <process.h>#define MY_PROCESS_ERROR(Condition) do{ if (!(Condition))  goto Exit0; } while (false)static DWORD g_sdwTickCountOld = 0;                // 上一次的tick计数static LARGE_INTEGER g_slgProcessTimeOld;        // 保存进程上一次的时间占用static DWORD g_sdwProcessorCoreNum = 0;            // 处理器核心数static HANDLE g_shExitEvent = NULL;                // 线程退出控制typedef struct _TARGET_PROCESS{    DWORD        dwProcessId;                    // 进程ID}TARGET_PROCESS, *PTARGET_PROCESS;/*@brief 获取找到的与指定进程名相符的第一个进程ID* @param [in]        cpszExeFileName        进程可执行文件名(不带路径)* @param [in/out]    dwPID                返回找到的名字符合的第一个进程ID* @return 成功 : S_OK    失败 : 错误码*/HRESULT FindFirstProcessIdByName(const TCHAR* cpszExeFileName, DWORD &dwPID){    HRESULT hr = E_FAIL;    PROCESSENTRY32 pe = { 0 };    HANDLE hSnapshot = NULL;    if (NULL == cpszExeFileName)    {        hr = HRESULT_FROM_WIN32(ERROR_BAD_ARGUMENTS);        goto Exit0;    }    pe.dwSize = sizeof(PROCESSENTRY32);    hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);    if (INVALID_HANDLE_VALUE == hSnapshot)    {        hr = HRESULT_FROM_WIN32(GetLastError());        goto Exit0;    }      if (FALSE == Process32First(hSnapshot, &pe))    {        hr = HRESULT_FROM_WIN32(ERROR_NO_MORE_FILES);        goto Exit0;    }    hr = S_FALSE;    do    {        if (0 == _tcsicmp(cpszExeFileName, pe.szExeFile))        {            dwPID = pe.th32ProcessID;            hr = S_OK;            break;        }    }while(Process32Next(hSnapshot, &pe));Exit0:    if(hSnapshot)    {        CloseHandle(hSnapshot);        hSnapshot = NULL;    }    return hr;}/*@brief 获取进程的Cpu占用率* @param [in]    hProcess            进程句柄* @param [in]    dwElepsedTime        取样间隔时间(毫秒)* @return 成功 : cpu占用率    失败 : -1*/int GetProcessCpuPercent(const HANDLE hProcess, const DWORD dwElepsedTime){    int nProcCpuPercent = 0;    BOOL bRetCode = FALSE;    FILETIME CreateTime, ExitTime, KernelTime,UserTime;    LARGE_INTEGER lgKernelTime;    LARGE_INTEGER lgUserTime;    LARGE_INTEGER lgCurTime;    bRetCode = GetProcessTimes(hProcess, &CreateTime, &ExitTime, &KernelTime, &UserTime);    if (bRetCode)    {        lgKernelTime.HighPart = KernelTime.dwHighDateTime;        lgKernelTime.LowPart = KernelTime.dwLowDateTime;        lgUserTime.HighPart = UserTime.dwHighDateTime;        lgUserTime.LowPart = UserTime.dwLowDateTime;        lgCurTime.QuadPart = (lgKernelTime.QuadPart + lgUserTime.QuadPart) / 10000;        nProcCpuPercent = (int)((lgCurTime.QuadPart - g_slgProcessTimeOld.QuadPart) * 100 / dwElepsedTime);        g_slgProcessTimeOld = lgCurTime;        nProcCpuPercent = nProcCpuPercent / g_sdwProcessorCoreNum;    }    else    {        nProcCpuPercent = -1;    }    return nProcCpuPercent;}unsigned __stdcall WorkerThread(void *pArg){    HRESULT hr = E_FAIL;    HANDLE hProcess = NULL;    DWORD dwProcessId = 0;    DWORD dwRetVal = 0;    DWORD dwCurrentTickCount = 0;    DWORD dwElapsedTime = 0;    int nProcessCpuPercent = 0;        TARGET_PROCESS *pTargetProcess = (TARGET_PROCESS *)pArg;    dwProcessId = pTargetProcess->dwProcessId;    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION , FALSE, dwProcessId);    MY_PROCESS_ERROR(hProcess);    do     {        dwRetVal = WaitForSingleObject(g_shExitEvent, 1000);        if (WAIT_OBJECT_0 == dwRetVal ||            WAIT_FAILED == dwRetVal            )        {            break;        }        dwCurrentTickCount = GetTickCount();        dwElapsedTime = dwCurrentTickCount - g_sdwTickCountOld;        g_sdwTickCountOld = dwCurrentTickCount;        nProcessCpuPercent = GetProcessCpuPercent(hProcess, dwElapsedTime);        wprintf(L"cpu = %d\n", nProcessCpuPercent);    } while (1);    Exit0:    if (hProcess)    {        CloseHandle(hProcess);        hProcess = NULL;    }        return 0;}int _tmain(int argc, _TCHAR* argv[]){    HRESULT hr = E_FAIL;        HANDLE hThread = NULL;    unsigned int uiTid = 0;    SYSTEM_INFO sysInfo = { 0 };    TARGET_PROCESS struTargetProcess;    if (argc > 1)    {        hr = FindFirstProcessIdByName(argv[1], struTargetProcess.dwProcessId);        if (S_OK != hr)        {            _tprintf(_T("Can't find process \'%s\' ret=0x%X\n"), argv[1], hr);            goto Exit0;        }        GetSystemInfo(&sysInfo);        g_sdwProcessorCoreNum = sysInfo.dwNumberOfProcessors;        g_shExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL);        MY_PROCESS_ERROR(g_shExitEvent);        hThread = (HANDLE)_beginthreadex(NULL, 0, WorkerThread, &struTargetProcess, 0, &uiTid);        MY_PROCESS_ERROR(hThread);        _getch();        SetEvent(g_shExitEvent);        WaitForSingleObject(hThread, INFINITE);    }    else    {        _tprintf(_T("Please input a process name.\n"));    }Exit0:    if (hThread)    {        CloseHandle(hThread);        hThread = NULL;    }    if (g_shExitEvent)    {        CloseHandle(g_shExitEvent);        g_shExitEvent = NULL;    }    return 0;}

from:http://www.cnblogs.com/xwj-pandababy/articles/2567498.html


0 0