title: PowerCLI performance
body: <p>I have written a PowerCLI script to retrieve relevant information plus usage stats for the previous month for our VM's and output it a csv but it's painfully slow. Can anyone suggest any improvements that could help speed up the report.</p>
  
  <p>I'm fairly new to powershell/PowerCLI so any help would be gratefully received</p>
  
  <pre><code>$todayMidnight = (Get-Date -Hour 0 -Minute 0 -Second 0).AddMinutes(-1)
  $EndOfLastMonth = (Get-Date -Year (get-date).Year -Month (get-date).Month -Day 1 -Hour 0 -Minute 0 -Second 0).AddMinutes(-1)
  $FirstofLastMonth = $EndOfLastMonth.AddMonths(-1)
  $workingDays = "Monday","Tuesday","Wednesday","Thursday","Friday"
  $dayStart = New-Object DateTime(1,1,1,8,0,0) 
  $dayEnd = New-Object DateTime(1,1,1,18,0,0)
  
  $CSVFile = Read-Host "Enter Filename for csv"
  
  $Report = @()
  
  Connect-VIServer "VCServer" | Out-Null
  
  $ServerList = Get-VM |  Where-Object {$_.VMHost.Name -ne "192.168.106.161" -and $_.PowerState -eq "PoweredOn" } | Sort-Object Name
  
  $Counter = 1
  
  foreach ($Server in $ServerList) {
  
      $VMInfo = {} | select Name, OS, VMHost, IPAddress, NumCPU, TotalMemMB, AvgMemPcnt, MaxMemPcnt, AvgCPUMhz, AvgCPUPcnt, MaxCPUPcnt
      $VMInfo.name = $Server
  
      $MaxCPUPcnt = get-vm $Server | Get-Stat -Stat cpu.usage.average -IntervalSecs 1 |
          Where-Object {  $workingDays -contains $_.Timestamp.DayOfWeek -and $_.Timestamp.TimeOfDay -gt $dayStart.TimeOfDay -and $_.Timestamp.TimeOfDay -lt $dayEnd.TimeOfDay} |
          Measure-Object value -Max | select Maximum
  
      $MaxMemPcnt = get-vm $Server | Get-Stat -Stat mem.usage.average -IntervalSecs 1 |
      Where-Object {  $workingDays -contains $_.Timestamp.DayOfWeek -and $_.Timestamp.TimeOfDay -gt $dayStart.TimeOfDay -and $_.Timestamp.TimeOfDay -lt $dayEnd.TimeOfDay} |
      Measure-Object value -Max | select Maximum
  
      $AvgCPUMhz = get-vm $Server | Get-Stat -Stat cpu.usagemhz.average -IntervalMins 5 |
          Where-Object {  $workingDays -contains $_.Timestamp.DayOfWeek -and $_.Timestamp.TimeOfDay -gt $dayStart.TimeOfDay -and $_.Timestamp.TimeOfDay -lt $dayEnd.TimeOfDay} |
          Measure-Object value -Average | select Average
  
      $AvgCPUPcnt = get-vm $Server | Get-Stat -Stat cpu.usage.average -IntervalMins 5 |
          Where-Object {  $workingDays -contains $_.Timestamp.DayOfWeek -and $_.Timestamp.TimeOfDay -gt $dayStart.TimeOfDay -and $_.Timestamp.TimeOfDay -lt $dayEnd.TimeOfDay} |
          Measure-Object value -Average | select Average
  
      $AvgMemPcnt = get-vm $Server | Get-Stat -Stat mem.usage.average -IntervalMins 5 |
          Where-Object {  $workingDays -contains $_.Timestamp.DayOfWeek -and $_.Timestamp.TimeOfDay -gt $dayStart.TimeOfDay -and $_.Timestamp.TimeOfDay -lt $dayEnd.TimeOfDay} |
          Measure-Object value -Average | select Average
  
      $VMinfo.MaxCPUPcnt =  [math]::round($MaxCPUPcnt.Maximum,2)
      $VMinfo.MaxMemPcnt =  [math]::round($MaxMemPcnt.Maximum,2)
      $VMinfo.AvgCPUMhz =  [math]::round($AvgCPUMhz.Average,2)
      $VMInfo.AvgCPUPcnt = [math]::round($AvgCPUPcnt.Average,2)
      $VMInfo.AvgMemPcnt = [math]::round($AvgMemPcnt.Average,2)
  
      $TotalMemMB = get-vm $Server | select MemoryMB
      $VMInfo.TotalMemMB = $TotalMemMB.MemoryMb
  
      $VMInfo.VMHost = (get-vm gbvc0007 | Get-VMHost).name
  
      $VMInfo.OS = (Get-VM $Server | Get-View).summary.config.GuestFullName
  
      $VMInfo.IPAddress =  (Get-VM $Server | Get-VIew).summary.guest.ipaddress
  
      $VMInfo.NumCPU = (Get-VM $Server | Get-VIew).summary.config.NumCPU
  
      $Report += $VMInfo
  
      $Counter++
  }
  
  clear
  $Report | ft -AutoSize
  
  $Report | Export-Csv -Path $CSVFile
  
  Disconnect-VIServer -Server * -Confirm:$false
  </code></pre>