Pregunta

tengo un samurizar config que muestra un gráfico de uso de CPU similar al Administrador de tareas.

¿Cómo puedo mostrar también el nombre del proceso con el porcentaje de uso de CPU más alto actual?

Me gustaría que esto se actualice, como máximo, una vez por segundo.Samurize puede llamar a una herramienta de línea de comandos y mostrar su resultado en la pantalla, por lo que esta también podría ser una opción.


Más aclaraciones:

He investigado escribir mi propia aplicación C# .NET de línea de comando para enumerar la matriz devuelta por System.Diagnostics.Process.GetProcesses(), pero la clase de instancia Process no parece incluir una propiedad de porcentaje de CPU.

¿Puedo calcular esto de alguna manera?

¿Fue útil?

Solución

Con PowerShell:

Get-Process | Sort-Object CPU -desc | Select-Object -first 3 | Format-Table CPU,ProcessName -hidetableheader

devuelve algo como:

  16.8641632 System
   12.548072 csrss
  11.9892168 powershell

Otros consejos

Lo que desea obtener es el uso instantáneo de la CPU (más o menos)...

En realidad, el uso instantáneo de CPU para un proceso no existe.En lugar de eso, debes realizar dos mediciones y calcular el uso promedio de la CPU; la fórmula es bastante simple:

AvgCpuUsed = [TotalCPUTime(proceso,tiempo2) - TotalCPUTime(proceso,tiempo1)] / [tiempo2-tiempo1]

Cuanto menor sea la diferencia entre Tiempo2 y Tiempo1, más "instantánea" será su medición.El Administrador de tareas de Windows calcula el uso de la CPU con un intervalo de un segundo.Descubrí que es más que suficiente e incluso podrías considerar hacerlo en intervalos de 5 segundos porque el acto de medir en sí mismo consume ciclos de CPU...

Entonces, primero, para obtener el tiempo promedio de 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;
}

Ahora, para la carga "instantánea" de la CPU necesitarás una clase especializada:

 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;
    }
  }
}

Deberías llamar a esa clase desde un temporizador (o cualquier método de intervalo que desees) para cada proceso que desea monitorear, si quieres todos los procesos solo usa el Proceso.GetProcesses método estático

Aprovechando la respuesta de Frederic y utilizando el código al final de la página aquí (para ver un ejemplo de uso, consulte este post) para unirse al conjunto completo de procesos obtenidos de Get-Process, obtenemos lo siguiente:

$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

Lo que da un ejemplo de salida de

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

Es posible que puedas utilizar Pmon.exe para esto.Puedes obtenerlo como parte del Herramientas del kit de recursos de Windows (El enlace es a la versión Server 2003, que aparentemente también se puede usar en XP).

De alguna manera

Get-Process | Sort-Object CPU -desc | Select-Object -first 3 | Format-Table CPU,ProcessName,TotalProcessorTime -hidetableheader

no estaba obteniendo la información de la CPU de la máquina remota.Tuve que pensar en esto.

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

Gracias por la fórmula, Jorge.No entiendo muy bien por qué hay que dividir por la cantidad de núcleos, pero los números que obtengo coinciden con el Administrador de tareas.Aquí está mi código de 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

También puedes hacerlo de esta manera:-

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];
    }

Uso:-

static void Main()
    {
        Process mxp=getProcessWithMaxCPUUsage();
        Console.WriteLine(mxp.ProcessName);
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top