This post is updated and replaced by Avoid-Array-Addition-Tip-update

Like many others, I’m a fan of PowerShell.tiPS by Daniel Schroeder (aka @deadlydog), and the other day a really nice tip submitted by: Santiago Squarzon appeared in my PowerShell console. The tip was so sweet that I just had to go ahead and expand the example and then used Measure-Command to test the benefit described by Santiago’s tip.

Firstly, the tip

# --------------------------- Avoid Array addition [Performance] ---------------------------
# Array addition is an expensive and inefficient operation and can usually be replaced by PowerShell explicit loop assignment.

# Use a `List<T>` instead in those cases when adding to a collection while looping is required.
Example:
# Array addition:
$items = @()
foreach ($i in 0..10) {
    $items += $i
}

# Can be easily replaced with explicit assignment:
$items = foreach ($i in 0..10) {
    $i
}

# And, when not possible, a List<T> is recommended:
$items = [System.Collections.Generic.List[int]]::new()
foreach ($i in 0..10) {
    $items.Add($i)
}

More information: https://learn.microsoft.com/en-us/powershell/scripting/dev-cross-plat/performance/script-authoring-considerations#array-addition

Tip submitted by: Santiago Squarzon (santisq)

Expanding the example with Measure-Command

PowerShell is full of many great Commands Cmdlets and Modules, and one of my favourites is Measure-Command.
Measure-Command makes it very easy to assess the performance of your commands, and to test improvements. And that’s what I show in the example. I’ve wrapped the tip with Measure-Command to reveal how much faster the code gets when following that great tip.

Hope you like the goodies

$upperBound = 10000

Measure-Command {
    # Array addition:
    $items = @()
    foreach ($i in 0..$upperBound) {
        $items += $i
    }
} | Select-Object TotalMilliseconds                # TotalMilliseconds: 2076.1273

Measure-Command {
    # Can be easily replaced with explicit assignment:
    $items = foreach ($i in 0..$upperBound) {
        $i
    }
} | Select-Object TotalMilliseconds                # TotalMilliseconds: 15.3416

Measure-Command {
    # And, when not possible, a List<T> is recommended:
    $items = [System.Collections.Generic.List[int]]::new()
    foreach ($i in 0..$upperBound) {
        $items.Add($i)
    }
} | Select-Object TotalMilliseconds                # TotalMilliseconds: 11.2543

TotalMilliseconds
-----------------
        2076.1273 # Array addition
          15.3416 # Explicit assignment
          11.2543 # List<T>

Performance improvements

See What’s New in PowerShell 7.5 for some relevant additional info on this topic, where PowerShell 7.5-rc.1 has included PR#23901 from @jborean93 that improves the performance of the += operation for an array of objects.

Tip: there is a great example of performance improvements measurement at the same What’s New in PowerShell 7.5 link above.


<
Previous Post
Convert CIDR to subnet mask in PowerShell
>
Next Post
Avoid Array Addition - Tip updated