#powershell #optimization #vectorization
#powershell #оптимизация #векторизация
Вопрос:
Есть ли способ объединить массивы в PowerShell аналогично объединению столбцов фрейма данных в Python Pandas с concat
или в R с cbind
вместо перебора каждого элемента?
Ниже приведен воспроизводимый пример, который связывает четыре массива вместе в виде четырех столбцов в объекте PowerShell. Как мне избавиться от for
цикла и получить те же результаты?
$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, 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
$TopTable = For ($i=0; $i -lt $NameArray.Length; $i ) {
if ($NameArray[$i].InstanceName -eq '_total') {continue}
if ($NameArray[$i].InstanceName -eq 'memory compression') {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;
Memory = $MemArray[$i].CookedValue;
}
}
$TopTable | sort -des $SortCol | select -f $top |`
select Name, ID,`
@{Name='CPU'; Expression = {("{0:N1}%" -f $_.CPU) } },`
@{Name='Memory'; Expression = {("{0:N0} K" -f ($_.Memory /1kb) )} }
}
myTop -SortCol Memory -top 30 | ft -a
Ответ №1:
Я думаю, что PowerShell не предоставляет способа объединения столбцов. В этом случае это может соответствовать Group-Object
.
function myTop([string]$SortCol = "CPU", [int]$Top = 30)
{
$LogicalProcessors = (Get-WmiObject Win32_processor NumberOfLogicalProcessors).NumberOfLogicalProcessors
Get-Counter 'Process(*)ID Process','Process(*)% Processor Time','Process(*)Working Set - Private' -ea SilentlyContinue |
foreach CounterSamples |
where InstanceName -notin "_total","memory compression" |
group { $_.Path.Split("\")[3] } |
foreach {
[pscustomobject]@{
Name = $_.Group[0].InstanceName
ID = $_.Group[0].CookedValue
CPU = if($_.Name -eq "idle") { $_.Group[1].CookedValue / $LogicalProcessors } else { $_.Group[1].CookedValue }
Memory = $_.Group[2].CookedValue / 1KB
}
} |
sort -des $SortCol |
select -f $Top @(
"Name","ID"
@{ n = "CPU"; e = { ("{0:N1}%" -f $_.CPU) } }
@{ n = "Memory"; e = { ("{0:N0} K" -f $_.Memory) } }
)
}
myTop -SortCol Memory -top 10 | ft -a
Комментарии:
1. Один вызов
Get-Counter
выполняется намного быстрее, чем несколько вызовов.2. необходимо изменить
CPU = if($_.Name -eq "idle")
CPU = if($_.Group[0].InstanceName -eq "idle")
, чтобы убедиться, что процессор «бездействующего» процесса делится на количество логических процессоров.