Write-Progress Issues
So, you wrote a script and included nifty progress bar, fairly simple. But your script runs slow, especially in a Powershell terminal. Let me explain how you can address this issue. First, the relevant part of the script:
for ($i=0; $i -le 10000; $i++) {
Write-Progress -Activity Testing -Status something -PercentComplete (($i/10000)*100)
}
As an example let’s tun it in the ISE, wrapped in Measure-Command to time the performance and…
Measure-Command -Expression {
for ($i=0; $i -le 10000; $i++) {
Write-Progress -Activity Testing -Status something -PercentComplete (($i/10000)*100)
}
} | Select-Object -Property TotalMilliSeconds
1406 Milliseconds! That’s not to bad! Now if we run it again in our terminal the result is much different.
Measure-Command -Expression {
for ($i=0; $i -le 10000; $i++) {
Write-Progress -Activity Testing -Status something -PercentComplete (($i/10000)*100)
}
} | Select-Object -Property TotalMilliSeconds
16054 Milliseconds to display a simple progress-bar?!
Why the terminal is slower
Displaying and updating the progress-bar is an expensive operation because the GUI needs to be re-rendered. The ISE and the terminal use a different GUI and from our results above we can see that updating the ISE GUI is less expensive.
Resolution
Resolving this issue is pretty straight forward, just update the gui less frequent. For example update every 10% instead of every loop iteration. This is where mod
or %
can help.
Measure-Command -Expression {
$count = 10000
[int]$interval = $count * 0.1
for ($i=0; $i -le $count; $i++)
{
if ($i % $interval -eq 0)
{
Write-Progress -Activity Testing -Status something -PercentComplete (($i/10000)*100)
}
}
} | Select-Object -Property TotalMilliSeconds
67! We improved our performance by 99.6%
There you have it, the proper way to write a progress-bar.