Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PowerShell Performance Pointers

Guy Leech
November 10, 2021

PowerShell Performance Pointers

Hints and tips to make PowerShell code perform better.

Presented at the PowerShell Berlin User Group, 10th November 2021

Guy Leech

November 10, 2021
Tweet

More Decks by Guy Leech

Other Decks in Technology

Transcript

  1. ▪ Wrote my first code (on Commodore PET) in 1980

    (in BASIC) ▪ Unix developer in C/C++ for 6 years after graduation from University of Manchester in 1988 ▪ Started with Windows (NT 3.51) in 1995 via Citrix ▪ Invented & wrote what is now Ivanti Application Control security product ▪ Freelance consultant writing PowerShell for software vendors like ControlUp, Flexxible IT, Avanite ▪ Current Microsoft MVP, Citrix CTP, VMware vExpert, Parallels VIPP @guyrleech
  2. ▪ Not usually ▪ Nowhere near as important as (correct)

    functionality ▪ Does taking 15 minutes instead of 5 really matter? ▪ How much time/money will it take to make it significantly faster? ▪ Do not run scripts on key infrastructure servers use a jump box ▪ Think about performance when writing code ▪ Expressions evaluated left to right in an if statement ▪ Filter as far left as possible @guyrleech
  3. ▪ Measure-Command ▪ Once is not enough ▪ Watch for

    file system caching and other optimisations ▪ Get-Date ▪ [Diagnostics.Stopwatch] ▪ Guy's clock/stopwatch ▪ PSProfiler @guyrleech
  4. ▪ Don't keep evaluating/fetching/setting the same thing ▪ Start-Sleep –

    consider the impact of the script on your environment ▪ Reduce the process' base priority ▪ (Get-Process –id $pid).PriorityClass = 'BelowNormal' ▪ Do you need to repeat the looping? ▪ Do you need Write-Verbose, Write-Progress etc on every iteration? ▪ .Where (collections) versus Where-Object ▪ ForEach versus ForEach-Object versus .ForEach (collections) ▪ . { Process { } } @guyrleech
  5. ▪ For arrays and strings, takes a complete copy of

    existing object ▪ Can get slow for large items ▪ It is ok for hashtables ▪ Arrays ▪ Assign results to an array rather than adding to it within the loop ▪ Wrap in @( ) to avoid PowerShell's "helpful" array flattening "feature" ▪ Instead use System.Collections.Generic.List[object] which has Add/Remove methods ▪ Iterate backwards if calling Remove() ▪ Do not use System.Collections.ArrayList ▪ Strings ▪ $oldstring = $oldstring + $newstring ▪ $oldstring = "$oldstring$newstring" ▪ $oldstring = -join ( $oldstring , $newstring ) @guyrleech
  6. ▪ Is it quicker to keep in memory than look

    up individually/once? ▪ Get-ADUser ▪ Get-BrokerMachine ▪ But what is the memory overhead? ▪ Be selective what properties are cached ▪ Trim own working set ▪ Destroy unused data/variables ▪ [gc]::Collect() ▪ Hashtable or array ? ▪ Unique key ? ▪ Hashtable of arrays ▪ Sort ? ▪ Most likely to be accessed near the start ▪ Binary search via index ? ▪ Number of elements ▪ .Where() versus Where-Object ▪ .Where takes optional count x, for where-object pipe through Select-Object –First x ▪ [System.Management.Automation.WhereOperatorSelectionMode] @guyrleech
  7. ▪ How long does it take PowerShell to find a

    command? ▪ Always use Import-Module in scripts in case of new/non-persistent profile ▪ In a loop, can add time locating command ▪ Could module qualify (also helps avoid ambiguity/incorrect cmdlet use) ▪ VMware.VimAutomation.Core\Get-VM versus Hyper-V\Get-VM ▪ Get-Command ▪ Call with . or & @guyrleech
  8. ▪ Can the tasks be split into separate, unrelated, activities?

    ▪ Pwsh 7.x has ForEach-Object -Parallel ▪ Windows PowerShell has Invoke-Command –ComputerName ▪ Can use localhost ▪ Needs remoting configured ▪ Runspaces ▪ Not as scary as you might think ▪ Take some working code (give credit) and modify @guyrleech