Имя процесса с максимальной загрузкой процессора

StackOverflow https://stackoverflow.com/questions/51684

Вопрос

у меня есть Самуризировать config, который показывает график использования ЦП, аналогичный диспетчеру задач.

Как мне также отобразить имя процесса с текущим самым высоким процентом использования ЦП?

Я бы хотел, чтобы это обновлялось не чаще одного раза в секунду.Samurize может вызывать инструмент командной строки и отображать его вывод на экране, так что это тоже может быть вариантом.


Дальнейшее уточнение:

Я исследовал написание собственного приложения C# .NET для командной строки для перечисления массива, возвращаемого из System.Diagnostics.Process.GetProcesses(), но класс экземпляра процесса, похоже, не включает свойство процента ЦП.

Могу ли я это как-то посчитать?

Это было полезно?

Решение

С PowerShell:

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

возвращает что-то вроде:

  16.8641632 System
   12.548072 csrss
  11.9892168 powershell

Другие советы

То, что вы хотите получить, это мгновенное использование процессора (вроде как)...

На самом деле мгновенного использования процессора процессом не существует.Вместо этого вам придется сделать два измерения и вычислить среднюю загрузку процессора, формула довольно проста:

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

Чем меньше разница между Временем2 и Временем1, тем более «мгновенным» будет ваше измерение.Диспетчер задач Windows рассчитывает загрузку ЦП с интервалом в одну секунду.Я обнаружил, что этого более чем достаточно, и вы можете даже подумать о том, чтобы делать это с интервалом в 5 секунд, потому что сам процесс измерения требует циклов ЦП...

Итак, во-первых, чтобы получить среднее время процессора

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

теперь для «мгновенной» загрузки процессора вам понадобится специализированный класс:

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

Вы должны вызвать этот класс из таймера (или любого другого интервального метода, который вам нравится) для каждый процесс, который вы хотите отслеживать, если вы хотите, чтобы все процессы просто использовали Process.GetProcesses статический метод

Основываясь на ответе Фредерика и используя код внизу страницы. здесь (пример использования см. этот post), чтобы присоединиться к полному набору процессов, полученных от Get-Process, мы получаем следующее:

$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

Что дает пример вывода

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

Возможно, вы сможете использовать Pmon.exe для этого.Вы можете получить его как часть Инструменты набора ресурсов Windows (ссылка на версию Server 2003, которую, очевидно, можно использовать и в XP).

Как-то

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

не получал информацию о процессоре с удаленного компьютера.Мне пришлось это придумать.

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

Спасибо за формулу, Хорхе.Я не совсем понимаю, зачем нужно делить на количество ядер, но цифры у меня совпадают с Диспетчером задач.Вот мой код 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

Вы также можете сделать это следующим образом: -

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

Использование:-

static void Main()
    {
        Process mxp=getProcessWithMaxCPUUsage();
        Console.WriteLine(mxp.ProcessName);
    }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top