PerformanceCounter.NextValue() returns 常数值 CPU 负载

PerformanceCounter.NextValue() returns constant value for CPU load

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

我知道必须在第一次调用 NextValue() 时初始化它的 PerformanceCounter 问题(参见 this question,等等),所以我实现了一个非常简单的静态 class 将数据缓存一秒钟,实际上仅每秒或更短时间访问一次 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;
    }
}

...在我执行它之前,这一切都很好而且花花公子。我在 Windows 4 核 10 x64 VM 和 Windows 4 核 7 x64 iron 上尝试了 运行 - 在这两种情况下,returned 值都在徘徊400左右,不管我做什么。

我得到的典型值在 395–401 范围内,偶尔会下降到 365 或跳到 405。我读到的值与任何一个上的实际 CPU 负载都没有关系我测试过的机器,如任务管理器、性能监视​​器所示,或者确实是常识。

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

我做错了什么?这是否应该仅 return 我的应用程序线程使用 CPU ?我是否误解了数据?

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

是的,_Total 进程数占用的处理器时间,包括您在任务管理器中看到的假 "System Idle Process",在 4 核机器上总计为 400%。

如果将 "Process" 更改为 "Processor",您可能会更喜欢这个数字。如果要匹配任务管理器显示的值,则需要将 "Process" 更改为 "Processor Information"。一个新类别,它试图生成一个更真实的数字,以补偿具有涡轮增压的处理器、具有 NUMA 节点的机器以及您从超线程获得的较低性能。您需要阅读 this blog post 以了解细节。