How Can We Help?
Limit cmdlet calls in a loop
While it is perfectly alright to run a loop in the following way.
1 2 3 4 5 6 |
foreach($vm in Get-VM){ Get-Stat -Entity $vm -Stat cpu.usage.average -Realtime -MaxSamples 1 | Select-Object Timestamp, @{N='VM';E={$_.Entity.Name}}, @{N='CPU%';E={$_.Value}} } |
You can improve the runtime of your script by using just one call to the Get-Stat cmdlet.
1 2 3 4 5 6 |
Get-Stat -Entity (Get-VM) -Stat cpu.usage.average -Realtime -MaxSamples 1 | Group-Object -Property {$_.Entity.Name} | %{ $_ | Select-Object @{N='Timestamp';E={$_.Group.Timestamp}}, @{N='VM';E={$_.Name}}, @{N='CPU%';E={$_.Group.Value}} } |
Instead of having to deal with the overhead of the Get-Stat cmdlet multilpe times, in the second snippet, the Get-Stat cmdlet is only called once. The script uses the Group-Object cmdlet to split out the results per VM.
The second snippet still has room for improvement.
You can skip the VMs that are not powered on and only obtain the aggregate data, if that fits the requirement.
1 2 3 4 5 6 7 |
$vm = Get-VM | Where-Object{$_.PowerState -eq 'PoweredOn'} Get-Stat -Entity $vm -Stat cpu.usage.average -Realtime -MaxSamples 1 -Instance '' | Group-Object -Property {$_.Entity.Name} | ForEach-Object{ $_ | Select-Object @{N='Timestamp';E={$_.Group[0].Timestamp}}, @{N='VM';E={$_.Name}}, @{N='CPU%';E={$_.Group[0].Value}} } |