3

这个问题“如何在 C# 中获取 CPU 使用率?” 显示了在 .NET 中获取计算机当前 CPU 使用率 (%) 的一些方法。

由于 CPU 使用率波动非常频繁,我认为当前的 CPU 使用率通常不能很好地指示计算机的繁忙程度(例如,用于调度或负载平衡目的)。有没有一种有效的方法来获得最后 x 分钟的平均 CPU 使用率,例如最后 5 分钟?

我正在考虑类似方法 GetAverageCpuUsage(int period) 可以由负载平衡或调度模块调用的方法。

4

3 回答 3

7

实际上,这正是另一个问题中第二个最受好评的答案中的PerformanceCounter所做的,它们的测量时间仅超过 1 秒。

NextValue()它给你的百分比是最后一次在柜台上进行的 CPU seance 的平均百分比。因此,如果您想要过去 5 分钟的平均 cpu,只需NextValue()每 5 分钟调用一次。

这是一篇很好的文章,解释了如何使用性能计数器。

于 2013-02-05T05:58:12.800 回答
1

上面的答案为计算 CPU 使用率的方法提供了一个很好的例子。但我想指出一些不正确且被误导的东西。SubtractTimes 函数需要稍有不同。

private UInt64 SubtractTimes(ComTypes.FILETIME a, ComTypes.FILETIME b)
    {
        UInt64 aInt = ((UInt64)(a.dwHighDateTime << 32)) | (UInt32)a.dwLowDateTime;
        UInt64 bInt = ((UInt64)(b.dwHighDateTime << 32)) | (UInt32)b.dwLowDateTime;

        return aInt - bInt;
    }

注意 lowDateTime 的 UINT32。这是因为,至少在 C# 中,comtype.FILETIME 结构将 DWORD 强制转换为 int32,因此如果该值大于 MAX 有符号 Int,您会看到一个负值,这种情况绝不应该出现。如果您将其直接转换为“UINT64”类型,则在内部为保留符号,它首先转换为 Int64,然后转换为 UInt64,因此您会看到不正确的值。相反,您希望将 lowDateTime 转换为 Uint32 类型以消除负号,然后转换为 UInt64(这将自动发生,因为它是 | 操作的一部分)。dwHighDateTime 组件也应该如此,但这很好,因为它通常不应该超过 MaxInt (嗯,这又取决于你的用例)。

于 2016-12-29T18:59:42.683 回答
0

尝试类似:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using ComTypes = System.Runtime.InteropServices.ComTypes;
using System.Threading;
using System.Diagnostics;

namespace example1
{
    public class CpuUsage
    {
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool GetSystemTimes(
                    out ComTypes.FILETIME lpIdleTime,
                    out ComTypes.FILETIME lpKernelTime,
                    out ComTypes.FILETIME lpUserTime
                    );

        ComTypes.FILETIME _prevSysKernel;
        ComTypes.FILETIME _prevSysUser;

        TimeSpan _prevProcTotal;

        Int16 _cpuUsage;
        DateTime _lastRun;
        long _runCount;

        public CpuUsage()
        {
            _cpuUsage = -1;
            _lastRun = DateTime.MinValue;
            _prevSysUser.dwHighDateTime = _prevSysUser.dwLowDateTime = 0;
            _prevSysKernel.dwHighDateTime = _prevSysKernel.dwLowDateTime = 0;
            _prevProcTotal = TimeSpan.MinValue;
            _runCount = 0;
        }

        public short GetUsage()
        {
            short cpuCopy = _cpuUsage;
            if (Interlocked.Increment(ref _runCount) == 1)
            {
                if (!EnoughTimePassed)
                {
                    Interlocked.Decrement(ref _runCount);
                    return cpuCopy;
                }

                ComTypes.FILETIME sysIdle, sysKernel, sysUser;
                TimeSpan procTime;

                Process process = Process.GetCurrentProcess();
                procTime = process.TotalProcessorTime;

                if (!GetSystemTimes(out sysIdle, out sysKernel, out sysUser))
                {
                    Interlocked.Decrement(ref _runCount);
                    return cpuCopy;
                }

                if (!IsFirstRun)
                {
                    UInt64 sysKernelDiff = SubtractTimes(sysKernel, _prevSysKernel);
                    UInt64 sysUserDiff = SubtractTimes(sysUser, _prevSysUser);

                    UInt64 sysTotal = sysKernelDiff + sysUserDiff;

                    Int64 procTotal = procTime.Ticks - _prevProcTotal.Ticks;

                    if (sysTotal > 0)
                    {
                        _cpuUsage = (short)((100.0 * procTotal) / sysTotal);
                    }
                }

                _prevProcTotal = procTime;
                _prevSysKernel = sysKernel;
                _prevSysUser = sysUser;

                _lastRun = DateTime.Now;

                cpuCopy = _cpuUsage;
            }
            Interlocked.Decrement(ref _runCount);

            return cpuCopy;

        }

        private UInt64 SubtractTimes(ComTypes.FILETIME a, ComTypes.FILETIME b)
        {
            UInt64 aInt = ((UInt64)(a.dwHighDateTime << 32)) | (UInt64)a.dwLowDateTime;
            UInt64 bInt = ((UInt64)(b.dwHighDateTime << 32)) | (UInt64)b.dwLowDateTime;

            return aInt - bInt;
        }

        private bool EnoughTimePassed
        {
            get
            {
                const int minimumElapsedMS = 250;
                TimeSpan sinceLast = DateTime.Now - _lastRun;
                return sinceLast.TotalMilliseconds > minimumElapsedMS;
            }
        }

        private bool IsFirstRun
        {
            get
            {
                return (_lastRun == DateTime.MinValue);
            }
        }
    }
}

在你的代码中使用它之后:

   CpuUsage _cu = new CpuUsage();
   string cpuUsage = _cu.GetUsage();

在某事上有所帮助

于 2013-04-19T14:08:34.903 回答