简体   繁体   English

加快PowerShell Get-Counter和Get-Process的速度

[英]Speed up PowerShell Get-Counter and Get-Process

The following PowerShell code works, generates the output shown below, and is reproducible. 以下PowerShell代码可以正常工作,生成如下所示的输出,并且是可重现的。

The general question is: how can I speed it up? 一般的问题是:如何加快速度?

The biggest bottlenecks are the Get-Process and Get-Counter cmdlets. 最大的瓶颈是Get-ProcessGet-Counter cmdlet。

EDITED based on @LotPings comments. 根据@LotPings注释进行编辑

$LogicalProcessors = (Get-WmiObject –class Win32_processor 
    -Property NumberOfLogicalProcessors).NumberOfLogicalProcessors;

function myTop([String]$SortCol='CPU', [Int32]$top=30) {
    $NameArray = get-counter '\Process(*)\ID Process' -EA SilentlyContinue | 
        Select -Expand CounterSamples | Select InstanceName
    $IdArray = get-counter '\Process(*)\ID Process' -EA SilentlyContinue | 
        Select -Expand CounterSamples | Select CookedValue
    $CpuArray = get-counter '\Process(*)\% Processor Time' -EA SilentlyContinue | 
        Select -Expand CounterSamples | Select CookedValue
    $MemArray = get-counter '\Process(*)\Working Set - Private' -EA SilentlyContinue | 
        Select -Expand CounterSamples | Select CookedValue

    $procTbl = get-process | select ID, Name, Description, MainWindowTitle

    $TopTable = @()
    For ($i=0; $i -lt $NameArray.Length; $i++) {
            $procIndex = [array]::indexof($procTbl.ID, [Int32]$IdArray[$i].CookedValue)
            if ($NameArray[$i].InstanceName -eq '_total') {continue}
            if ($NameArray[$i].InstanceName -eq 'memory compression') {continue}
            if ($NameArray[$i].InstanceName -eq 'idle') {
                $NewRow = [PSCustomObject]@{
                Name = $NameArray[$i].InstanceName;
                ID = $IdArray[$i].CookedValue;
                CPU = ($CpuArray[$i].CookedValue) / $LogicalProcessors;
                Mem = $MemArray[$i].CookedValue;
                procID = $procTbl.ID[$procIndex];
                Description = $procTbl.Description[$procIndex];
                Title = $procTbl.MainWindowTitle[$procIndex];
                }
            $TopTable += $NewRow
            } else {
                $NewRow = [PSCustomObject]@{
                Name = $NameArray[$i].InstanceName;
                ID = $IdArray[$i].CookedValue;
                CPU = $CpuArray[$i].CookedValue;
                Mem = $MemArray[$i].CookedValue;
                procID = $procTbl.ID[$procIndex];             
                Description = $procTbl.Description[$procIndex];
                Title = $procTbl.MainWindowTitle[$procIndex];
                }
            $TopTable += $NewRow
            }
        }

    $TopTable | sort -des $SortCol | select -f $top |`
    select Name, ID,`
        @{Name='CPU'; Expression = {("{0:N1}%" -f $_.CPU) } },`
        @{Name='Mem'; Expression = {("{0:N0} K" -f ($_.Mem /1kb) )} },
        Description, Title
}

While(1) {$p = myTop -SortCol CPU -top 12 | ft -a ; sleep 0; cls; $p}

Output (refresh rate approximately 2 seconds): 输出(刷新率约2秒):

Name                  ID CPU   Mem          Description        Title
----                  -- ---   ---          -----------        -----
memory compression  2768 0.0%  996,516 kb
code                8828 0.0%  232,084 kb   Visual Studio Code
chrome             28620 0.0%  217,088 kb   Google Chrome
code               41596 0.0%  180,076 kb   Visual Studio Code
chrome             33772 0.0%  140,976 kb   Google Chrome      Speed up PowerShell Get-Counter and Get-Pro...
code               22600 0.0%  127,952 kb   Visual Studio Code
teams              27412 0.0%  105,656 kb   Microsoft Teams
powershell         55692 1.5%  95,596 kb    Windows PowerShell
mcshield            8596 0.0%  93,784 kb
onedrive           59644 0.0%  80,796 kb    Microsoft OneDrive
code               21708 0.0%  79,688 kb    Visual Studio Code
powershell         64228 0.0%  74,508 kb                       Administrator: Windows PowerShell

Due to my locale with different counter names, I can't test myself: 由于我的区域设置使用不同的计数器名称,因此无法测试自己:

## Q:\Test\2019\04\14\SO_55678790.ps1
$LogicalProcessors = (Get-WmiObject –class Win32_processor).NumberOfLogicalProcessors;

function myTop([String]$SortCol='CPU', [Int32]$top=30) {
    $NameArray = get-counter '\Process(*)\ID Process' -EA SilentlyContinue |
        Select -Expand CounterSamples | Select-Object InstanceName,CookedValue
    $CpuArray = get-counter '\Process(*)\% Processor Time' -EA SilentlyContinue |
        Select -Expand CounterSamples | Select-Object CookedValue
    $MemArray = get-counter '\Process(*)\Working Set - Private' -EA SilentlyContinue |
        Select -Expand CounterSamples | Select-Object CookedValue

    $proc = Get-Process

    $TopTable = For ($i=0; $i -lt $NameArray.Length; $i++) {
        $procIndex = [array]::indexof($proc.Id, [Int32]$NameArray[$i].CookedValue)
        if ($NameArray[$i].InstanceName -eq '_total') {continue}
        if ($NameArray[$i].InstanceName -eq 'idle') {
            $CPU = ($CpuArray[$i].CookedValue) / $LogicalProcessors
        } else {
            $CPU = $CpuArray[$i].CookedValue;
        }
        [PSCustomObject]@{
            Name        = $NameArray[$i].InstanceName
            ID          = $NameArray[$i].CookedValue
            CPU         = $CPU
            Mem         = $MemArray[$i].CookedValue
            Description = $proc[$procIndex].Description
            Title       = $proc[$procIndex].MainWindowTitle
        }
    }
    $TopTable | Sort-Object -Descending $SortCol | Select-Object -First $top Name,ID,
      @{Name='CPU'; Expression = {("{0:N1}%" -f $_.CPU) } },
      @{Name='Mem'; Expression = {("{0:N0} kb" -f ($_.Mem /1kb) )} },
      Description, Title
}

While(1) {
    myTop -SortCol CPU -top 12 | ft -a
    sleep 0
    cls
    # pause
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM