Prof. Powershell
Fanfare for the Common Parameter Part 4: Outbuffer
There is one more common parameter you might need or want to use to control this buffering behavior. It is called –Outbuffer.
- By Jeffery Hicks
- 07/16/2013
In our previous lesson we looked at the –OutVariable common parameter. I pointed out a potential pitfall when used in an expression like this:
PS C:\> get-process -ov ps | where {$_.id -le $ps.count*20} | measure-object | format-list Count
Count : 11
Because PowerShell sends objects through the pipeline in batches. But there is one more common parameter you might need or want to use to control this buffering behavior. It is called –Outbuffer and has an alias of –ob. The value is an integer indicating the number of objects to buffer at any given time.
Using the example above, I could revise the expression like this:
PS C:\> get-process -ov ps -outbuffer 150 | where {$_.id -le $ps.count*20} | Measure-Object | format-list count
Count : 27
I know that there are no more than 150 processes on my computer so by setting the OutBuffer value high, the Get-Process command finishes and the $ps variable is fully populated. This means the Where-Object expression will work as expected.
Using OutBuffer can play a role in performance. For example, in my Scripts folder I have 1869 PowerShell scripts. Let's try an experiment:
PS C:\> measure-command { dir c:\scripts -filter *.ps1 -Recurse | where {$_.lastwritetime -gt (Get-date).AddDays(-30)} -ov a}
This command took 678 milliseconds to run. I saved the results of the Where-Object expression to $a which has 33 files.
Buffering one file at a time took 710 milliseconds.
PS C:\> measure-command { dir c:\scripts -filter *.ps1 -Recurse -ob 1 | where {$_.lastwritetime -gt (Get-date).AddDays(-30)} -ov a}
Buffering 1000 file objects at a time
PS C:\> measure-command { dir c:\scripts -filter *.ps1 -Recurse -ob 1000 | where {$_.lastwritetime -gt (Get-date).AddDays(-30)} -ov a }
This took about 620 milliseconds. The performance gains are modest and probably really won't be noticeable except very large sets of objects. Here's one more example:
PS C:\> measure-command {1..10000 | foreach {$_*3}}
This took 793 milliseconds to run. I then tried with –Outbuffer using different values.
PS C:\> measure-command {1..10000 | foreach {$_*3} -ob $X }
Here are my results:
- 1000 = 777ms
- 5000 = 775ms
- 10000 = 804ms
Running this again with numbers 1 to 100000 gave these results:
- Default = 7.8 seconds
- 1000 = 7.93 seconds
- 5000 = 7.46 seconds
- 10000 = 7.94 seconds
The conclusion I would draw is that using –Outbuffer is as much an art as it is a science. I'm not sure there is any hard and fast rule as to when to use this parameter and with what value. But if you have a special case and are trying to eke out a bit more performance, fine tuning with the OutBuffer common parameter may be just what you need.
About the Author
Jeffery Hicks is an IT veteran with over 25 years of experience, much of it spent as an IT infrastructure consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He is a multi-year recipient of the Microsoft MVP Award in Windows PowerShell. He works today as an independent author, trainer and consultant. Jeff has written for numerous online sites and print publications, is a contributing editor at Petri.com, and a frequent speaker at technology conferences and user groups.