使用HyperThreading正确测量CPU使用率?

时间:2015-11-25 19:20:38

标签: c++ winapi cpu-usage

我知道有关如何使用以下两种方法之一测量CPU使用率的答案有几个答案:

有些日子我现在很难用这两种方法执行我的程序的CPU使用率测量 - 使用这两种机制我得到的CPU使用率小于任务管理器或Process Explorer中显示的CPU使用率。这些工具是如何做到这一点的,这是否与启用超线程有关?我将在没有HyperThreding的情况下在CPU上执行测试,但是如果有人能指出我在这里缺少什么,我会非常感激。

为了说明我尝试过的内容,这里是执行基于PDH的测量的代码:

class CCpuUsageMonitor
{
public:
    CCpuUsageMonitor(const wchar_t* pProcessName)
    {

        GetSystemInfo(&m_SystemInfo);
        auto nStatus = PdhOpenQuery(NULL, NULL, &m_hPdhQuery);
        _ASSERT(nStatus == ERROR_SUCCESS);
        nStatus = PdhAddCounter(m_hPdhQuery, L"\\Processor(_Total)\\% Processor Time", NULL, &m_hPdhCpuUsageCounter);
        _ASSERT(nStatus == ERROR_SUCCESS);
        wchar_t pCounterPath[PDH_MAX_COUNTER_PATH];
        StringCbPrintf(pCounterPath, PDH_MAX_COUNTER_PATH, L"\\Process(%s)\\%% Processor Time", pProcessName);
        nStatus = PdhAddCounter(m_hPdhQuery, pCounterPath, NULL, &m_hPhdProcessCpuUsageCounter);
        _ASSERT(nStatus == ERROR_SUCCESS);
    }

    ~CCpuUsageMonitor()
    {
        PdhCloseQuery(&m_hPdhQuery);
    }

    void CollectSample()
    {
        auto nStatus = PdhCollectQueryData(m_hPdhQuery);
        _ASSERT(nStatus == ERROR_SUCCESS);
    }

    double GetCpuUsage()
    {
        DWORD nType;
        PDH_FMT_COUNTERVALUE CounterValue;
        auto nStatus = PdhGetFormattedCounterValue(m_hPdhCpuUsageCounter, PDH_FMT_DOUBLE | PDH_FMT_NOCAP100, &nType, &CounterValue);
        _ASSERT(nStatus == ERROR_SUCCESS);
        return CounterValue.doubleValue;
    }

    double GetProcessCpuUsage()
    {
        DWORD nType;
        PDH_FMT_COUNTERVALUE CounterValue;
        auto nStatus = PdhGetFormattedCounterValue(m_hPhdProcessCpuUsageCounter, PDH_FMT_DOUBLE | PDH_FMT_NOCAP100, &nType, &CounterValue);
        _ASSERT(nStatus == ERROR_SUCCESS);
        return CounterValue.doubleValue / m_SystemInfo.dwNumberOfProcessors;
    }

private:
    SYSTEM_INFO m_SystemInfo;
    HANDLE m_hPdhQuery;
    HANDLE m_hPdhCpuUsageCounter;
    HANDLE m_hPhdProcessCpuUsageCounter;
};

使用第二种方法,我基本上在代码运行之前和之后通过GetProcessTimes()获取两个处理时间快照,减去并除以墙上时间乘以处理器数量。

1 个答案:

答案 0 :(得分:1)

以下是我过去使用过的一些链接以及一篇关于为什么GetThreadTimes出错的好文章(我不会将其用作可靠的数据来源):

http://blog.kalmbachnet.de/?postid=28

https://msdn.microsoft.com/en-us/library/aa392397(VS.85).aspx

http://www.drdobbs.com/windows/win32-performance-measurement-options/184416651

https://msdn.microsoft.com/en-us/library/aa394279(VS.85).aspx

你似乎很顺利,知识渊博,这些链接应该让你至少朝着正确的方向前进。