监视任何进程的CPU峰值超过X%,持续Y秒

时间:2015-01-29 20:04:33

标签: .net vb.net performance cpu performancecounter

我想在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

1 个答案:

答案 0 :(得分:1)

您可以尝试类似下面的代码。实际上,每次调用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属性时,您将收到错误。