让 WMI 更快地读取处理器负载

发布于 2024-09-15 07:47:55 字数 1854 浏览 3 评论 0原文

我有一个 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 对象仅更新处理器加载属性,但我不知道该怎么做。

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

I have a C# application, where I have to get the processor load. According to the accepted answer for this question, my options are to either use performance counters from either WMI or the System.Diagnostics namespace. I have a problem with the System.Diagnostics performance counter (as documented here), so my only option is to use WMI. The following code shows how I read the processor load using 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.
        }
    }
}

My problem is, that it takes around half a second to retrieve the processor utilization, as can be seen from this typical snippet of output:

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

My guess is that at least part of the reason, that it takes so long to sample the load, is that the Get method call also updates other properties of the ManagementObject object. So my question is: How can I make the Get method call update faster? I would guess, that the solution is to somehow tell the ManagementObject object to only update the processor load property, but I don't know how to do that.

As an aside, it is curious that the sample times of the output are so stable around half a second, but I am not sure if that can give any hints toward the solution.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ゝ偶尔ゞ 2024-09-22 07:47:55

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

如果您缩短周期,则计算值的准确度会降低。如果它太短,数字将在 0 到 100 之间跳跃。

据我所知,您无法更改 WMI 查询中的采样率。您可以通过直接读取性能计数器来获得更快(且噪音更大)的更新。您可以在我的答案中找到示例代码 此帖子

It has to be slow, there's no other way. The CPU core is either running at full bore or it is turned off by a HALT instruction. From which it is woken up again by an interrupt. The effective CPU load is an average calculated over a period, typically one second. The amount of time it was running divided by the period.

If you make the period shorter then the calculated value gets less accurate. Make it too short and the number will just jump between 0 and 100.

You cannot change the sample rate in the WMI query afaik. You can get quicker (and noisier) updates by reading the performance counter directly. You'll find sample code in my answer in this thread.

夏末 2024-09-22 07:47:55

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

Recommendation: Use the Win32_PerfRawData_PerfOS_Processor performance counter and the PERF_100NSEC_TIMER_INV algorithm instead of the formatted counters. The rounding can lead to some fairly inaccurate results.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文