获取最近x分钟内计算机的平均CPU使用率

时间:2013-02-05 05:54:02

标签: c# .net cpu-usage system.diagnostics

此问题"How to get the CPU Usage in C#?"显示了获取.NET中计算机当前CPU使用率(%)的一些方法。

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

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

3 个答案:

答案 0 :(得分:5)

实际上,这正是PerformanceCounter来自the 2nd most upvoted answer的另一个问题,它们的测量时间超过1秒。

它给出的百分比是计数器上最后NextValue()的cpu集合的平均百分比。因此,如果您想要在过去5分钟内获得平均cpu,请每5分钟只调用一次NextValue()

Here is a good article解释如何使用效果计数器。

答案 1 :(得分: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,则会看到一个负值,这绝不应该是这种情况。如果你把它直接投射到&#34; UINT64&#34; type,在内部用于保留符号,首先将其转换为Int64,然后转换为UInt64,以便您看到不正确的值。相反,您希望将lowDateTime转换为Uint32类型以消除负号,然后转换为UInt64(这将自动发生,因为它是|操作的一部分)。同样应该适用于dwHighDateTime conponent,但这很好,因为它通常不应超过MaxInt(好吧,这又取决于你的用例)。

答案 2 :(得分: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();

帮助了某些事情