Pergunta

eu tenho um Samurizar config que mostra um gráfico de uso da CPU semelhante ao gerenciador de tarefas.

Como também exibo o nome do processo com a maior porcentagem de uso de CPU atual?

Gostaria que isso fosse atualizado, no máximo, uma vez por segundo.Samurize pode chamar uma ferramenta de linha de comando e exibir sua saída na tela, então isso também pode ser uma opção.


Maior esclarecimento:

Eu investiguei a criação de meu próprio aplicativo c # .NET de linha de comando para enumerar a matriz retornada de System.Diagnostics.Process.GetProcesses (), mas a classe de instância Process não parece incluir uma propriedade de porcentagem de CPU.

Posso calcular isso de alguma forma?

Foi útil?

Solução

Com PowerShell:

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

retorna algo como:

  16.8641632 System
   12.548072 csrss
  11.9892168 powershell

Outras dicas

O que você deseja obter é o uso instantâneo da CPU (mais ou menos) ...

Na verdade, o uso instantâneo da CPU para um processo não existe.Em vez disso você tem que fazer duas medições e calcular o uso médio da CPU, a fórmula é bastante simples:

AvgCpuUsed = [TotalCPUTime(process,time2) - TotalCPUTime(process,time1)] / [time2-time1]

Quanto menor for a diferença entre Time2 e Time1, mais "instantânea" será sua medição.O Gerenciador de Tarefas do Windows calcula o uso da CPU com um intervalo de um segundo.Descobri que isso é mais que suficiente e você pode até considerar fazê-lo em intervalos de 5 segundos, pois o próprio ato de medir ocupa ciclos de CPU...

Então, primeiro, para obter o tempo médio 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;
}

agora, para a carga "instantânea" da CPU você precisará de uma classe 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;
    }
  }
}

Você deve chamar essa classe a partir de um cronômetro (ou qualquer método de intervalo de sua preferência) para cada processo que você deseja monitorar, se você quiser todos os processos é só usar o Process.GetProcesses método estático

Com base na resposta de Frederic e utilizando o código na parte inferior da página aqui (para um exemplo de uso, veja esse post) para juntar o conjunto completo de processos obtidos de Get-Process, obtemos o seguinte:

$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

O que dá um exemplo de saída 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

Você pode ser capaz de usar Pmon.exe por esta.Você pode obtê-lo como parte do Ferramentas do Kit de Recursos do Windows (o link é para a versão Server 2003, que aparentemente também pode ser usada no XP).

De alguma forma

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

não estava obtendo as informações da CPU da máquina remota.Eu tive que inventar isso.

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

Obrigado pela fórmula, Jorge.Não entendo muito bem por que você precisa dividir pelo número de núcleos, mas os números que recebo correspondem ao Gerenciador de Tarefas.Aqui está meu código do 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

Você também pode fazer desta forma: -

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top