PerformanceCounter.NextValue()返回CPU负载的常量值

时间:2015-09-28 13:56:45

标签: c# cpu-usage performancecounter

我正在尝试推出自己的系统性能监视器,以便在出现过载时延迟执行部分服务器代码(在IIS下运行某些Web服务)。我要解决的第一件事就是CPU过载。

我知道PerformanceCounter问题必须通过第一次调用NextValue()来初始化它(参见this question等),所以我实现了一个非常简单的静态类来缓存一秒钟的数据,实际上每秒只能访问一次PerformanceCounter对象。我知道它目前不是线程安全的,但在当前的原型设计阶段我并不关心它。

所以,说了这么多,这是我现在的代码:

public static class SystemPerformance
{
    private static PerformanceCounter TotalProcessorTimeCounter =
        new PerformanceCounter("Process", "% Processor Time", "_Total");
    private static DateTime CacheRefreshed;
    private static float CachedValue = 0f;
    private const float MIN_DELTA_SECONDS = 1f;

    public static float ReadCPU()
    {
        if ((DateTime.Now - CacheRefreshed).TotalSeconds > MIN_DELTA_SECONDS)
            // Stale cache
            return ReadFromCounter();

        // Good cache
        return CachedValue;
    }

    private static float ReadFromCounter()
    {
        CachedValue = TotalProcessorTimeCounter.NextValue();
        CacheRefreshed = DateTime.Now;
        return CachedValue;
    }
}

...这一切都很好,花花公子,直到我执行它。我尝试在具有4个内核的Windows 10 x64 VM上运行它,在具有4个内核的Windows 7 x64铁上运行它 - 在这两种情况下,无论我做什么,返回值都会徘徊在400左右。

我得到的典型值在395-401范围内,偶尔下降到365或跳到405.我读到的值与我测试的任何一台机器上的实际CPU负载没有任何关联,如任务管理器,性能监视器或实际常识所示。

测试方法很简单:SystemPerformance.ReadCPU()由简单的Windows窗体中的按钮触发,输出以相同的形式显示在文本框中。当CPU处于准空闲状态时,我按下那个按钮,当其他进程正在执行操作并加载CPU时,我也按下它。

我做错了什么?这应该只返回应用程序线程的CPU使用率吗?我是否误解了数据?

1 个答案:

答案 0 :(得分:2)

   new PerformanceCounter("Process", "% Processor Time", "_Total");

是的,_Total进程数所占用的处理器时间,包括您在任务管理器中看到的虚假“系统空闲进程”,在4核计算机上总是会增加400%。

如果将“处理”更改为“处理器”,您可能更喜欢这个数字。如果要匹配任务管理器显示的值,则需要将“处理”更改为“处理器信息”。尝试生成更实际数字的新类别,该数字补偿了具有turbo boost的处理器,具有NUMA节点的计算机以及从超线程获得的较低性能。您需要阅读this blog post了解细节。