2

我有一个 C# 应用程序,我必须在其中获得处理器负载。根据这个问题的公认答案,我的选择是使用来自 WMI 或 System.Diagnostics 命名空间的性能计数器。我的 System.Diagnostics 性能计数器有问题(如此所述),所以我唯一的选择是使用 WMI。以下代码显示了我如何使用 WMI 读取处理器负载:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;

namespace ProcessorUtilizationSpike
{
    class Program
    {
        private static ManagementObject processor;

        static void Main(string[] args)
        {
            processor = new ManagementObject("Win32_PerfFormattedData_PerfOS_Processor.Name='_Total'");

            while(true)
            {
                PrintTimedMeasure();
            }
        }

        static void PrintTimedMeasure()
        {
            DateTime start = DateTime.Now;
            UInt64 wmi = WMIMeasure();
            DateTime stop = DateTime.Now;
            Console.WriteLine("wmi : " + wmi + ", time: " + (stop - start));
        }

        static UInt64 WMIMeasure()
        {
            processor.Get();
            return ((UInt64)processor.Properties["PercentProcessorTime"].Value); // this property corresponds to a UInt64, see the Type property.
        }
    }
}

我的问题是,检索处理器利用率大约需要半秒钟,从这个典型的输出片段可以看出:

wmi : 6, time: 00:00:00.5156250
wmi : 3, time: 00:00:00.5156250
wmi : 4, time: 00:00:00.5000000
wmi : 3, time: 00:00:00.5156250
wmi : 3, time: 00:00:00.5000000

我的猜测是,至少部分原因是采样负载需要很长时间,因为 Get 方法调用还更新了 ManagementObject 对象的其他属性。所以我的问题是:如何使 Get 方法调用更新更快?我猜想,解决方案是以某种方式告诉 ManagementObject 对象只更新处理器负载属性,但我不知道该怎么做。

顺便说一句,奇怪的是输出的采样时间在半秒左右如此稳定,但我不确定这是否可以为解决方案提供任何提示。

4

2 回答 2

3

一定要慢,没有别的办法。CPU 内核要么全速运行,要么被 HALT 指令关闭。它被中断再次唤醒。有效 CPU 负载是在一段时间内计算的平均值,通常为一秒。它运行的时间量除以时间段。

如果您缩短周期,则计算值会变得不那么准确。让它太短,数字只会在 0 到 100 之间跳跃。

您不能在 WMI 查询 afaik 中更改采样率。通过直接读取性能计数器,您可以获得更快(更嘈杂)的更新。您将在我的回答中找到示例代码

于 2010-08-19T18:31:13.370 回答
2

建议:使用 Win32_PerfRawData_PerfOS_Processor 性能计数器和 PERF_100NSEC_TIMER_INV 算法而不是格式化的计数器。四舍五入会导致一些相当不准确的结果。

于 2011-12-09T20:52:09.593 回答