When writing a PowerShell script, you are typically doing “something” with “something” and getting a result based on this “doing”.
This is all well and good, but after you have gotten your result what do you do with the data? Two common scenarios are writing the result either to the screen or to a file. If the script is doing a lot of calculations, it’s quite common to also give the user some kind of feedback while it’s working, to indicate that it’s actually doing what it’s suppose to do and that it haven’t stalled.
I have written a few blog post before about using a progress bar to give users visual feedback during long-running scripts. But after one of these posts, Brenton Blawat made me aware that using Write-Progress has it’s price on overall script execution time. I was aware that writing anything to the screen is associated with some kind of overhead, but I decided to do some tests to see exactly how much overhead are generated doing different kinds of interaction to either the screen or when writing results to a file.
I wrote a script performing the following tests:
- Test 1 (m1) – The baseline. This test is just performing an easy calculation, but is otherwise not doing anything with the results.
- Test 2 (m2) – This test is using Write-Host to write the result of the calculations to the screen.
- Test 3 (m3) – This test is using Write-Output to write the output of the calculations.
- Test 4 (m4) – This test is saving the results of the calculations to an Array.
- Test 5 (m5) – This test is saving the results of the calculations to an ArrayList.
- Test 6 (m6) – This test is using Write-Progress to create a progress bar while doing the calculations.
- Test 7 (m7) – This test is writing the result of the calculations to a file, doing file writes after each calculation.
- Test 8 (m8) – This test is writing the results of the calculations to a file, but only writing the file after all the calculations are done. In the meantime the results are saved in an ArrayList.
I ran the script, using Measure-Command to take the measurement data, a total of 10 times; 5 times in PowerShell ISE and 5 times from the PowerShell console.
I then calculated the average value of each of the 5 runs per test, so that I could see if it made any difference whether the script was run in ISE or the console.
This is a chart of the result of my testing:
And here a a table of the average data that I collected. All values are in milliseconds.
What surprised me the most was that, although running the script in the console was marginally faster in almost all cases, the Write-Progress cmdlet was significantly slower in the console compared to running it in the ISE.
Other than that I think most of the results were as expected.
I think the lessons learned can be summed up thus:
- Use Write-Output instead of Write-Host
- Use ArrayList instead of Array
- Use as few disk writes as possible
- Only use Write-Progress if you absolutely must
This is the test script I used in case you want to test for yourself: