Ky's Solutions
A developer tips and tricks
November 28, 2010 Categories: C/C++ and Windows. Tags: C, C++, Calculate CPU Usage, Calculate CPU Usage for Windows, and Windows. No Comments on Calculate CPU Usage in C/C++

What you want:

You want to calculate the CPU usage during your application run?

The Problem:

There’s no simple one function call that will return the CPU usage.

The Solution:

The CPU usage is based on usage time of your CPU.  Windows API provide a way to get the system time and process time.  The usage percent is equal to the total process time divided by the total system time times one hundred.

CPU% = (100.0 * (ProcessKernelTime + ProcessUserTime))/(SystemKernelTime + SystemUserTime)

To get the system time you will need to call GetSystemTimes(), which returns the idle, kernel and user time.  This function call is supported in Windows XP or higher versions. More info here.

To get the process time you will need to call GetProcessTimes(), which returns the creation, exit, kernel, and user time given the process handle.

Notes: the source code provided was created using Visual Studio 2010 Pro on Windows 7 machine, which defined the _WIN32_WINNT macro by default.   You may need to #define _WIN32_WINNT 0x0501 before the #include <windows.h> for the GetSystemTimes() function to work on older Visual Studio version.

// CpuUsage.cpp : Defines the entry point for the console application.
//
 
#include <Windows.h>
#include "stdafx.h"
#include <iostream>
#include <iomanip>
 
using namespace std;
 
ULONGLONG subtractTime(const FILETIME &a, const FILETIME &b)
{
    LARGE_INTEGER la, lb;
    la.LowPart = a.dwLowDateTime;
    la.HighPart = a.dwHighDateTime;
    lb.LowPart = b.dwLowDateTime;
    lb.HighPart = b.dwHighDateTime;
 
    return la.QuadPart - lb.QuadPart;
}
 
float getUsage(FILETIME *prevSysKernel, FILETIME *prevSysUser,
               FILETIME *prevProcKernel, FILETIME *prevProcUser,
               bool firstRun = false)
{
    FILETIME sysIdle, sysKernel, sysUser;
    FILETIME procCreation, procExit, procKernel, procUser;    
 
    if (!GetSystemTimes(&sysIdle, &sysKernel, &sysUser) ||
        !GetProcessTimes(GetCurrentProcess(), &procCreation, &procExit, &procKernel, &procUser))
    {
        // can't get time info so return
        return -1.;
    }
 
    // check for first call
    if (firstRun)
    {
        // save time info before return
        prevSysKernel->dwLowDateTime = sysKernel.dwLowDateTime;
        prevSysKernel->dwHighDateTime = sysKernel.dwHighDateTime;
 
        prevSysUser->dwLowDateTime = sysUser.dwLowDateTime;
        prevSysUser->dwHighDateTime = sysUser.dwHighDateTime;
 
        prevProcKernel->dwLowDateTime = procKernel.dwLowDateTime;
        prevProcKernel->dwHighDateTime = procKernel.dwHighDateTime;
 
        prevProcUser->dwLowDateTime = procUser.dwLowDateTime;
        prevProcUser->dwHighDateTime = procUser.dwHighDateTime;
 
	return -1.;
    }
 
    ULONGLONG sysKernelDiff = subtractTime(sysKernel, *prevSysKernel);
    ULONGLONG sysUserDiff = subtractTime(sysUser, *prevSysUser);
 
    ULONGLONG procKernelDiff = subtractTime(procKernel, *prevProcKernel);
    ULONGLONG procUserDiff = subtractTime(procUser, *prevProcUser);
 
    ULONGLONG sysTotal = sysKernelDiff + sysUserDiff;
    ULONGLONG procTotal = procKernelDiff + procUserDiff;
 
    return (float)((100.0 * procTotal)/sysTotal);
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    FILETIME prevSysKernel, prevSysUser;
    FILETIME prevProcKernel, prevProcUser;
    float usage = 0.0;
 
    // first call
    usage = getUsage(&prevSysKernel, &prevSysUser, &prevProcKernel, &prevProcUser, true);
 
    // do something to use some cpu
    for (int i=1; i<100000000; i++)
    {
        srand(i);
        int r = rand();
    }
    //wait 1 second
    Sleep(1000);
 
    // the actual cpu usage
    usage = getUsage(&prevSysKernel, &prevSysUser, &prevProcKernel, &prevProcUser);
    cout << "CPU% = " << setiosflags(ios::fixed) << setprecision(2) << usage;
 
    return 0;
}

Leave a Reply