在 Y 秒内监视 CPU 任何进程超过 X% 的峰值

Monitor CPU spikes of any process over X percent for Y seconds

我想在我们的 Windows Server 2008 机器上 运行 一个 .NET 控制台应用程序,它每 2 秒监控一次 CPU 使用情况。

如果任何单个应用程序连续两次使用 > 30% CPU,则应记录。

我将每 2 秒执行一次 "CheckCpu"...但我的问题是,如何确定每个进程的 CPU 使用情况?而且,高效 这样我就不会让我们的服务器陷入困境 :)

Dim lStrProcessCurrent As List(Of String)
Dim lStrProcessPrevious As List(Of String)

Private Sub CheckCpu()

    Dim pcc As New PerformanceCounterCategory("Process")

    'Clear "Current" run
    lStrProcessCurrent = New List(Of String)

    For Each instance As String In pcc.GetInstanceNames
        Using cnt As PerformanceCounter = New PerformanceCounter("Process", "ID Process", instance, True)

            Dim processName As String = cnt.InstanceName

 ' ?????  HOW TO DETERMINE CPU USAGE   ????
            Dim cpuUsage As Long = 31

            If cpuUsage >= 30 Then

                'Was over 30% in Previous check
                If lStrProcessPrevious.Contains(processName) Then
                    LogCpuSpike(processName)
                End If

                lStrProcessCurrent.Add(processName)
            End If

        End Using
    Next

    'Update "Previous" run
    lStrProcessPrevious = lStrProcessCurrent

End Sub

您可以尝试类似下面的代码。实际上,每次调用 CheckCpu() 时检查每个进程的 TotalProcessorTime,然后从之前的 运行 中减去它并除以两次检查之间经过的总时间。

Sub Main()

    Dim previousCheckTime As New DateTime
    Dim previousProcessList As New List(Of ProcessInformation)

    ' Kick off an initial check
    previousCheckTime = Now
    previousProcessList = CheckCPU(previousProcessList, Nothing)

    For i As Integer = 0 To 10
        Threading.Thread.Sleep(1000)

        previousProcessList = CheckCPU(previousProcessList, Now - previousCheckTime)
        previousCheckTime = Now

        For Each process As ProcessInformation In previousProcessList
            Console.WriteLine(process.Id & " - " & Math.Round(process.CpuUsage, 2).ToString & "%")
        Next
        Console.WriteLine("-- Next check --")
    Next

    Console.ReadLine()
End Sub

Private Function CheckCPU(previousProcessList As List(Of ProcessInformation), timeSinceLastCheck As TimeSpan) As List(Of ProcessInformation)

    Dim currentProcessList As New List(Of ProcessInformation)
    For Each process As Process In Process.GetProcesses()

        ' Id = 0 is the system idle process so we don't check that
        If process.Id <> 0 Then

            ' See if this process existed last time we checked
            Dim cpuUsage As Double = -1
            Dim previousProcess As ProcessInformation = previousProcessList.SingleOrDefault(Function(p) p.Id = process.Id)

            ' If it did then we can calculate the % of CPU time it has consumed
            If previousProcess IsNot Nothing AndAlso timeSinceLastCheck <> Nothing Then
                cpuUsage = ((process.TotalProcessorTime - previousProcess.TotalProcessorTime).Ticks / (Environment.ProcessorCount * timeSinceLastCheck.Ticks)) * 100
            End If

            ' Add to the current process list
            currentProcessList.Add(New ProcessInformation With {.Id = process.Id, .CpuUsage = cpuUsage, .TotalProcessorTime = process.TotalProcessorTime})
        End If

    Next

    Return currentProcessList

End Function

Class ProcessInformation
    Public Id As Integer
    Public TotalProcessorTime As TimeSpan
    Public CpuUsage As Double
End Class

在生产环境中,您可能应该添加更多检查,因为在调用 GetProcesses() 和处理列表之间可能会终止进程。如果进程已经消失,那么当您尝试访问 TotalProcessorTime 属性.

时,您将收到错误消息