【问题标题】:Monitor CPU spikes of any process over X percent for Y seconds在 Y 秒内监控超过 X% 的任何进程的 CPU 峰值
【发布时间】:2015-01-29 20:04:32
【问题描述】:

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

【问题讨论】:

  • 问题被否决但没有评论。我的问题不清楚吗?我没有投入第四次开发工作吗?
  • 非常确定 Windows 资源监视器可以做到这一点,而无需您编写任何代码。
  • 我认为这是个好问题。有些人会立即对他们不理解的问题投反对票。

标签: .net vb.net performance cpu performancecounter


【解决方案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 属性时会收到错误消息。

【讨论】:

  • 我最终使用了此代码的修改版本。非常感谢你的帮助! . . . . (CurrCPU - PreviousCPU) / (CurrTime - PreviousTime) * 100
猜你喜欢
  • 2017-07-22
  • 1970-01-01
  • 2016-11-27
  • 1970-01-01
  • 2014-12-01
  • 2013-06-02
  • 2023-04-02
  • 2013-01-06
  • 1970-01-01
相关资源
最近更新 更多