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

PowerShell Performance Tips

PowerShell Performance Tips

Guy shared from his five decades of software development experience to show tips and techniques on how to write efficient yet readable PowerShell code. Showing what is good, bad and ugly especially when looping and also how to use various collection types for data caching.

From the 45 minute session given at the PS Day UK conference in London, 3rd
March, 2023

Guy Leech

March 06, 2023
Tweet

More Decks by Guy Leech

Other Decks in Technology

Transcript

  1. PowerShell Performance Tips
    Guy Leech

    View full-size slide

  2. @guyrleech
    Many thanks to our sponsors!

    View full-size slide

  3. @guyrleech
    Guy Leech
    • Freelance consultant writing PowerShell for software
    vendors like ControlUp, Flexxible, Avanite, Netwrix,
    Parallels (Alludo)
    • Wrote my first code (on Commodore PET) in 1980 (in
    BASIC)
    • Unix developer in C/C++ for 6 years after graduation
    • Started with Windows (NT 3.51) in 1995 via Citrix
    • Invented & wrote what is now Ivanti Application
    Control security product

    View full-size slide

  4. @guyrleech
    Loops
     Don't keep evaluating/fetching/setting the same thing
     Do you need Write-Verbose, Write-Progress etc on every iteration?
     .Where (collections) versus Where-Object
     ForEach versus ForEach-Object versus .ForEach (collections)
     . { Process { } }
     Start-Sleep – consider the impact of the script on your environment
     Reduce the process' base priority
     (Get-Process –id $pid).PriorityClass = 'BelowNormal'

    View full-size slide

  5. @guyrleech
    +=
     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 )

    View full-size slide

  6. @guyrleech
    Caching Data
     Is it quicker/cheaper/safer 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]
     .Where always returns a collection

    View full-size slide

  7. @guyrleech
    Caching Commands
    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, it 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 &

    View full-size slide

  8. @guyrleech
    Parallelisation
    Can the tasks be split into separate, unrelated, activities?
    Pwsh 7.x has ForEach-Object –Parallel
     3rd party module available for Windows PowerShell
    Windows PowerShell has Invoke-Command –ComputerName
     Can use localhost
     Needs remoting configured
    Jobs
    Runspaces
     Not as scary as you might think!
     Take some working code (give credit) and modify

    View full-size slide

  9. @guyrleech
    But Is Performance Important?
    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

    View full-size slide

  10. @guyrleech
    Measuring Performance
    Measure-Command
    Once is not enough
    Watch for file system caching and other optimisations
    Get-Date
    [Diagnostics.Stopwatch]
    Guy's clock/stopwatch
    PSProfiler

    View full-size slide

  11. @guyrleech
    References
    https://gitgub.com/guyrleech
    https://github.com/IISResetMe/PSProfiler
    https://fatherjack.github.io/articles/Where
    https://4sysops.com/archives/understanding-
    powershell-begin-process-and-end-blocks/
    https://www.youtube.com/c/GuyLeech42

    View full-size slide

  12. @guyrleech
    PowerShell Workshops

    View full-size slide

  13. @guyrleech
    Q&A
    15 minutes

    View full-size slide