在 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 属性.
时,您将收到错误消息
我想在我们的 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 属性.
时,您将收到错误消息