PowerShell DISCUSSION

Building a large array with += in a PowerShell loop is very slow: what is the efficient way?

Started by testuser PowerShell performancearray += in loopgeneric Listforeach vs ForEach-Objecthashtable lookup
4 replies 248 views 5 participants
Latest activity · 30 Sep 2026

Building a large array with += in a PowerShell loop is very slow: what is the efficient way?

testuser PowerShell Forum
#1

My script parses a 200,000-line CSV log. It starts with $results = @() and does $results += $obj for each line inside a foreach loop. With small test files it is instant, but the full file takes many minutes, and the time seems to grow much faster than the file size.

Why is appending to an array so slow in PowerShell, and what should I use to collect a large number of objects?

Community replies 4

Re: Building a large array with += in a PowerShell loop is very slow: what is the efficient way?

#2

A PowerShell array is a fixed-size .NET array. It cannot grow, so $results += $obj allocates a new array one element longer, copies every existing element into it and discards the old one. Appending item number n therefore costs n copies, and the total for n items is about n² / 2. For 200,000 lines that is around 20 billion element copies, which is why doubling the file size roughly quadruples the run time.

Recent PowerShell 7 releases have reduced this penalty, but Windows PowerShell 5.1 pays it in full, and the alternatives below are the better pattern on every version.

Re: Building a large array with += in a PowerShell loop is very slow: what is the efficient way?

#3

The simplest fix is to let PowerShell collect the loop's output. Assign the whole loop to the variable and just emit each object inside it: $results = foreach ($line in $lines) { [pscustomobject]@{ Time = $line.Time; Value = [double]$line.Value } }. The engine gathers the output in a growable buffer and hands you an array at the end, with no copying per item.

The same works for if and switch statements and for pipelines, and it is usually the fastest pure-PowerShell option.

Re: Building a large array with += in a PowerShell loop is very slow: what is the efficient way?

#4

When you need to add items from several places, or remove them later, use a real list: $results = [System.Collections.Generic.List[object]]::new() and then $results.Add($obj). A list doubles its internal capacity when it fills up, so appending is constant time on average.

The same quadratic trap exists for strings. $text += $line in a loop copies the whole string every time, because .NET strings are immutable. Collect the pieces and use $pieces -join "`n" at the end, or a [System.Text.StringBuilder] with [void]$sb.AppendLine($line).

Re: Building a large array with += in a PowerShell loop is very slow: what is the efficient way?

#5

Look at the rest of the loop too. foreach ($x in $items) { } as a statement is noticeably faster than piping to ForEach-Object, which has per-item pipeline overhead; the pipeline's advantage is that it streams, so memory stays low on huge inputs. And a lookup such as $devices | Where-Object { $_.Id -eq $id } inside the loop scans the whole collection on every iteration. Build a hashtable once, $byId = @{}; foreach ($d in $devices) { $byId[$d.Id] = $d }, and each lookup becomes $byId[$id].

Measure before and after with Measure-Command { ... } on a 10,000-line sample so the comparison takes seconds, not minutes.

TEP COMMUNITY