Nome del processo con il massimo utilizzo della CPU
-
09-06-2019 - |
Domanda
Ho un Samurizzare config che mostra un grafico di utilizzo della CPU simile a Task Manager.
Come posso visualizzare anche il nome del processo con la percentuale di utilizzo della CPU attualmente più alta?
Vorrei che questo fosse aggiornato, al massimo, una volta al secondo.Samurize può richiamare uno strumento da riga di comando e visualizzarne l'output sullo schermo, quindi anche questa potrebbe essere un'opzione.
Ulteriori chiarimenti:
Ho studiato la scrittura della mia applicazione c# .NET da riga di comando per enumerare l'array restituito da System.Diagnostics.Process.GetProcesses(), ma la classe di istanza Process non sembra includere una proprietà percentuale della CPU.
Posso calcolarlo in qualche modo?
Soluzione
Con PowerShell:
Get-Process | Sort-Object CPU -desc | Select-Object -first 3 | Format-Table CPU,ProcessName -hidetableheader
restituisce un po' come:
16.8641632 System
12.548072 csrss
11.9892168 powershell
Altri suggerimenti
Quello che vuoi ottenere è l'utilizzo istantaneo della CPU (più o meno) ...
In realtà, l'utilizzo istantaneo della CPU per un processo non esiste.Devi invece fare due misurazioni e calcolare l'utilizzo medio della CPU, la formula è abbastanza semplice:
AvgCpuUsed = [TotalCPUTime(processo,tempo2) - TotalCPUTime(processo,tempo1)] / [tempo2-tempo1]
Minore è la differenza tra Tempo2 e Tempo1, più "istantanea" sarà la misurazione.Il Task Manager di Windows calcola l'utilizzo della CPU con un intervallo di un secondo.Ho scoperto che è più che sufficiente e potresti anche prendere in considerazione l'idea di farlo a intervalli di 5 secondi perché l'atto stesso della misurazione richiede cicli della CPU...
Quindi, innanzitutto, per ottenere il tempo medio della CPU
using System.Diagnostics;
float GetAverageCPULoad(int procID, DateTme from, DateTime, to)
{
// For the current process
//Process proc = Process.GetCurrentProcess();
// Or for any other process given its id
Process proc = Process.GetProcessById(procID);
System.TimeSpan lifeInterval = (to - from);
// Get the CPU use
float CPULoad = (proc.TotalProcessorTime.TotalMilliseconds / lifeInterval.TotalMilliseconds) * 100;
// You need to take the number of present cores into account
return CPULoad / System.Environment.ProcessorCount;
}
ora, per il carico "istantaneo" della CPU avrai bisogno di una classe specializzata:
class ProcLoad
{
// Last time you checked for a process
public Dictionary<int, DateTime> lastCheckedDict = new Dictionary<int, DateTime>();
public float GetCPULoad(int procID)
{
if (lastCheckedDict.ContainsKey(procID))
{
DateTime last = lastCheckedDict[procID];
lastCheckedDict[procID] = DateTime.Now;
return GetAverageCPULoad(procID, last, lastCheckedDict[procID]);
}
else
{
lastCheckedDict.Add(procID, DateTime.Now);
return 0;
}
}
}
Dovresti chiamare quella classe da un timer (o qualsiasi metodo di intervallo che preferisci) per ogni processo che desideri monitorare, se vuoi che tutti i processi usino semplicemente il file Process.GetProcesses metodo statico
Basandosi sulla risposta di Frederic e utilizzando il codice in fondo alla pagina Qui (per un esempio di utilizzo vedi Questo post) per unire l'intero set di processi ottenuti da Get-Process
, otteniamo quanto segue:
$sampleInterval = 3
$process1 = Get-Process |select Name,Id, @{Name="Sample1CPU"; Expression = {$_.CPU}}
Start-Sleep -Seconds $sampleInterval
$process2 = Get-Process | select Id, @{Name="Sample2CPU"; Expression = {$_.CPU}}
$samples = Join-Object -Left $process1 -Right $process2 -LeftProperties Name,Sample1CPU -RightProperties Sample2CPU -Where {$args[0].Id -eq $args[1].Id}
$samples | select Name,@{Name="CPU Usage";Expression = {($_.Sample2CPU-$_.Sample1CPU)/$sampleInterval * 100}} | sort -Property "CPU Usage" -Descending | select -First 10 | ft -AutoSize
Il che fornisce un esempio di output
Name CPU Usage
---- ---------
firefox 20.8333333333333
powershell_ise 5.72916666666667
Battle.net 1.5625
Skype 1.5625
chrome 1.5625
chrome 1.04166666666667
chrome 1.04166666666667
chrome 1.04166666666667
chrome 1.04166666666667
LCore 1.04166666666667
Potresti essere in grado di utilizzare Pmon.exe per questo.Puoi ottenerlo come parte del file Strumenti del Resource Kit di Windows (il collegamento è alla versione Server 2003, che apparentemente può essere utilizzata anche in XP).
Process.TotalProcessorTime
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.totalprocessortime.aspx
In qualche modo
Get-Process | Sort-Object CPU -desc | Select-Object -first 3 | Format-Table CPU,ProcessName,TotalProcessorTime -hidetableheader
non riceveva le informazioni sulla CPU dal computer remoto.Ho dovuto inventare questo.
Get-Counter '\Process(*)\% Processor Time' | Select-Object -ExpandProperty countersamples | Select-Object -Property instancename, cookedvalue| Sort-Object -Property cookedvalue -Descending| Select-Object -First 10| ft -AutoSize
Grazie per la formula, Jorge.Non capisco bene perché devi dividere per il numero di core, ma i numeri che ottengo corrispondono al Task Manager.Ecco il mio codice PowerShell:
$procID = 4321
$time1 = Get-Date
$cpuTime1 = Get-Process -Id $procID | Select -Property CPU
Start-Sleep -s 2
$time2 = Get-Date
$cpuTime2 = Get-Process -Id $procID | Select -Property CPU
$avgCPUUtil = ($cpuTime2.CPU - $cpuTime1.CPU)/($time2-$time1).TotalSeconds *100 / [System.Environment]::ProcessorCount
Puoi anche farlo in questo modo: -
public Process getProcessWithMaxCPUUsage()
{
const int delay = 500;
Process[] processes = Process.GetProcesses();
var counters = new List<PerformanceCounter>();
foreach (Process process in processes)
{
var counter = new PerformanceCounter("Process", "% Processor Time", process.ProcessName);
counter.NextValue();
counters.Add(counter);
}
System.Threading.Thread.Sleep(delay);
//You must wait(ms) to ensure that the current
//application process does not have MAX CPU
int mxproc = -1;
double mxcpu = double.MinValue, tmpcpu;
for (int ik = 0; ik < counters.Count; ik++)
{
tmpcpu = Math.Round(counters[ik].NextValue(), 1);
if (tmpcpu > mxcpu)
{
mxcpu = tmpcpu;
mxproc = ik;
}
}
return processes[mxproc];
}
Utilizzo:-
static void Main()
{
Process mxp=getProcessWithMaxCPUUsage();
Console.WriteLine(mxp.ProcessName);
}