ForEach vs ForEach-Object in PowerShell

In a current project where I use the PowerShell Management Agent from Søren Granfeldt to import information from a large LDAP catalog I discovered that there are some performance problems if you use PowerShell the incorrect way. One of these things is the use of ForEach vs ForEach-Object when enumerating a large collection of objects.

Searching the web I found this article from Anita, that helped me.

The results was stunning!

Look at this scenario where I search for objects in the LDAP catalog and the search returns +20 thousand objects.

I got $Response.Entries.Count is 21897

I then use the Measure-Command to compare the ForEach with the ForEach-Object way of iterating the objects.

First let’s see how the  generic ForEach-Object{} is doing.

(Measure-Command{$Response.Entries | ForEach-Object{$_.DistinguishedName} }).TotalMilliseconds
Resulted in: 1020 milliseconds

And then let’s see how ForEach(){} is doing when defining the type of object in the collection

Defining the entry object type like this
[System.DirectoryServices.Protocols.SearchResultEntry]$entry

and then measuring the result

(Measure-Command{ForEach($entry in $Response.Entries){$entry.DistinguishedName} }).TotalMilliseconds
Resulted in: 98 milliseconds

A performance factor of 10!.

And since a few of my collections in this project was actually returning more than 200 thousand objects you can imagine that I actually was able to see some effect.

One Reply to “ForEach vs ForEach-Object in PowerShell”

  1. Doug Finke

    Nice write up!

    Here is another subtle way to improve loops in PowerShell.

    Make Your PowerShell For Loops 4x Faster [http://www.dougfinke.com/blog/index.php/2011/01/16/make-your-powershell-for-loops-4x-faster/]

    Doug

    Reply

Leave a Reply to Doug Finke Cancel reply

Your email address will not be published. Required fields are marked *