c00000fd
c00000fd

Reputation: 22327

Method of getting current CPU utilization doesn't work reliably on Windows 10

I've been using the following method of getting current CPU utilization for the entire computer:

HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);

//Use a simple infinite loop to display the concept
for(;; ::Sleep(500))
{
    COORD coord = {0, 0};
    SetConsoleCursorPosition(hOut, coord);

    int nCpuUse = get_cpu_utilization_method_01();

    _tprintf(L"CPU Usage: %d\t", nCpuUse);
}


int get_cpu_utilization_method_01()
{
    int nRes = -1;

    FILETIME ftIdle, ftKrnl, ftUsr;
    if(GetSystemTimes(&ftIdle, &ftKrnl, &ftUsr))
    {
        static BOOL bUsedOnce = FALSE;
        static ULONGLONG uOldIdle = 0;
        static ULONGLONG uOldKrnl = 0;
        static ULONGLONG uOldUsr = 0;

        ULONGLONG uIdle = ((ULONGLONG)ftIdle.dwHighDateTime << 32) | ftIdle.dwLowDateTime;
        ULONGLONG uKrnl = ((ULONGLONG)ftKrnl.dwHighDateTime << 32) | ftKrnl.dwLowDateTime;
        ULONGLONG uUsr = ((ULONGLONG)ftUsr.dwHighDateTime << 32) | ftUsr.dwLowDateTime;

        //Only if we have previous values
        if(bUsedOnce)
        {
            ULONGLONG uDiffIdle = uIdle - uOldIdle;
            ULONGLONG uDiffKrnl = uKrnl - uOldKrnl;
            ULONGLONG uDiffUsr = uUsr - uOldUsr;

            if(uDiffKrnl + uDiffUsr)
            {
                //Calculate percentage
                nRes = (int)((uDiffKrnl + uDiffUsr - uDiffIdle) * 100 / (uDiffKrnl + uDiffUsr));

                //Check value and correct it (Just in case)
                if(nRes < 0)
                    nRes = 0;
                else if(nRes > 100)
                    nRes = 100;
            }
        }

        //Remember previous data
        bUsedOnce = TRUE;
        uOldIdle = uIdle;
        uOldKrnl = uKrnl;
        uOldUsr = uUsr;
    }

    return nRes;

}

But since Windows 10 I'm getting reports from the users of my software that the reading provided by this method can be wrong. Some people told me that it can report values as low as half of what Windows Task Manager was showing.

I've been running my own tests for a while and it seemed to be somewhat close to the Task Manager's reading on my laptop, but when I run it on my desktop with Intel Core i7-4770 CPU @ 3.40GHz with 4 physical and 8 logical cores, the reading seems to be consistently too low:

enter image description here

Note that I had Windows 7 installed on the same hardware (now running Windows 10) and it worked pretty reliably on Windows 7 then.

So any ideas how to make it work under Windows 10?

Upvotes: 2

Views: 1208

Answers (1)

user3272686
user3272686

Reputation: 849

Try this:

#include "TCHAR.h"
#include "pdh.h"

static PDH_HQUERY cpuQuery;
static PDH_HCOUNTER cpuTotal;

void init(){
PdhOpenQuery(NULL, NULL, &cpuQuery);
PdhAddCounter(cpuQuery, L"\\Processor(_Total)\\% Processor Time", NULL, &cpuTotal);
PdhCollectQueryData(cpuQuery);
}

double getCurrentValue(){
PDH_FMT_COUNTERVALUE counterVal;

PdhCollectQueryData(cpuQuery);
PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal);
return counterVal.doubleValue;
}

Upvotes: 2

Related Questions