【问题标题】:Method of getting current CPU utilization doesn't work reliably on Windows 10获取当前 CPU 利用率的方法在 Windows 10 上无法可靠运行
【发布时间】:2017-02-07 22:04:48
【问题描述】:

我一直在使用以下方法获取整台计算机的当前 CPU 利用率:

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;

}

但是从 Windows 10 开始,我收到了来自我的软件用户的报告,表明这种方法提供的读数可能是错误的。有人告诉我,它可以报告低至 Windows Task Manager 显示的值的一半。

我自己的测试已经运行了一段时间,它似乎有点接近笔记本电脑上的Task Manager 读数,但是当我在使用 Intel Core i7-4770 CPU @ 3.40 的台式机上运行它时具有 4 个物理内核和 8 个逻辑内核的 GHz,读数似乎始终过低:

请注意,我将 Windows 7 安装在相同的硬件上(现在运行 Windows 10),然后它在 Windows 7 上运行得非常可靠。

那么有什么想法可以让它在 Windows 10 下运行吗?

【问题讨论】:

  • 使用性能计数器
  • @DavidHeffernan:你知道,有趣的是taskmgr.exe 本身不使用performance counterspdh.dll
  • @c00000fd - 我通过this way 计算每个进程和空闲进程(这是 100 - CPU utilization for the entire computer)的 cpu 使用率,在 win10 上我得到了与 taskmgr 相同的结果。但这是使用本机 api 和时间来自 SYSTEM_PROCESS_INFORMATION

标签: c++ windows winapi windows-10 cpu-usage


【解决方案1】:

试试这个:

#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;
}

【讨论】:

  • 谢谢。我可以拨打getCurrentValue 的最低频率是多少?
  • 我也不确定它将如何处理多处理器/核心系统。我需要使用这些标志中的任何一个PDH_FMT_NOCAP100 | PDH_FMT_NOSCALE 来进行PdhGetFormattedCounterValue 调用吗?能详细点吗?
  • @c00000fd: “我可以调用 getCurrentValue 的最小频率是多少?” - 零。你的意思是问最大频率吗?
  • @IInspectable:不,我就是这个意思。您看,我发布的方法不能连续调用两次以获得可靠的结果。我认为这些电话之间应该至少有 250 毫秒。换句话说,它需要一些时间来收集信息。这就是我在这里问的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-26
  • 1970-01-01
  • 2020-10-24
  • 1970-01-01
  • 2010-10-26
相关资源
最近更新 更多