加速PowerShell Get-Counter和Get-Process

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了加速PowerShell Get-Counter和Get-Process相关的知识,希望对你有一定的参考价值。

以下PowerShell代码有效,生成如下所示的输出,并且可以重现。

一般的问题是:我怎样才能加快速度?

最大的瓶颈是Get-ProcessGet-Counter cmdlet。

根据@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}

输出(刷新率约为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
答案

由于我的语言环境有不同的计数器名称,我无法测试自己:

## Q:Test2019414SO_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
}

以上是关于加速PowerShell Get-Counter和Get-Process的主要内容,如果未能解决你的问题,请参考以下文章

PowerShell :: Get-Counter 显示错误的 CPU 使用率

Get-Counter 未检索到有效详细信息

在 Powershell 的表中格式化计数器数据

运行 powershell 命令以在 c# 上按进程获取 GPU 使用情况

如何使用名称中带有 * 的 Get-Counter 选择性能计数器

微调 Get-Counter 脚本以加快执行速度