This popped up some time ago but I finally sat down and did some complete testing on it. While writing deployment scripts, I couldn’t help but notice that they were taking forever to complete. Running the scripts by hand, I found that the majority of the time was being ate up by 'Invoke-WebRequest'
commands. A bit of searching later, I found some useful posts talking about the variable $ProgressPreference.
Once you set that $ProgressPreference
to 'SilentlyContinue'
… the downloads sped up. Not by a little bit, by quite a bit!
What is $ProgressPreference
?
$ProgressPreference
on the surface has to do with how progress updates are generated by a script, cmdlet or provider. You might recognize it as the bar that pops up at the top of the PowerShell Terminal when downloading something or running a script.
As per Microsoft, the values indicate the following:
- Stop: Doesn’t display the progress bar. Instead, it displays an error message and stops executing.
- Inquire: Doesn’t display the progress bar. Prompts for permission to continue. If you reply with Y or A, it displays the progress bar.
- Continue: (Default) Displays the progress bar and continues with execution.
- SilentlyContinue: Executes the command, but doesn’t display the progress bar.
You can find more information regarding these preferences and the $ProgressPreference
variable from Microsoft here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_preference_variables?view=powershell-5.1#progresspreference
Testing Environment
Tests are being run from my desktop computer.
- i9-12900k
- MAG Z690 TOMAHAWK WiFi
- Samsung 970 Evo Plus 1 TB
- Ethernet Connection
Internet connection at the time of these tests:
Test file is being pulled from https://testfile.org.
The 500MB file in particular – https://link.testfile.org/500MB.
Test Results
Using the Measure-Command
cmdlet, I recorded the time for each method 3 times. Providing all three results and an average of those times.
PowerShell 5.1 – 500MB File with $ProgressPreference set to default (Continue)
Command being used: Measure-Command { Invoke-WebRequest -Uri https://link.testfile.org/500MB -OutFile C:\Temp\500MB-File }
Test 1: 334.8981535 seconds
Test 2: 355.8534966 seconds
Test 3: 357.0668636 seconds
Average: 349.2728379 seconds
PowerShell 5.1 – 500MB File with $ProgressPreference set to SilentlyContinue
Command being used: $ProgressPreference = 'SilentlyContinue' ; Measure-Command { Invoke-WebRequest -Uri https://link.testfile.org/500MB -OutFile C:\Temp\500MB-File }
Test 1: 8.2345704 seconds
Test 2: 7.8108847 seconds
Test 3: 7.6026636 seconds
Average: 7.8827062 seconds
PowerShell 7.4 – 500MB File with $ProgressPreference set to Default (Continue)
Command being used: Measure-Command { Invoke-WebRequest -Uri https://link.testfile.org/500MB -OutFile C:\Temp\500MB-File }
Test 1: 8.4882387 seconds
Test 2: 8.6987693 seconds
Test 3: 7.8830255 seconds
Average: 8.3566778 seconds
PowerShell 7.4 – 500MB File with $ProgressPreference set to SilentlyContinue
Command being used: $ProgressPreference = 'SilentlyContinue' ; Measure-Command { Invoke-WebRequest -Uri https://link.testfile.org/500MB -OutFile C:\Temp\500MB-File }
Test 1: 8.169499 seconds
Test 2: 8.5426486 seconds
Test 3: 8.0165452 seconds
Average: 8.2428976 seconds
Results
You can see a drastic improvement between the 5.1 tests when adjusting the $ProgressPreference variable. Shaving off 341.3901317 seconds off of the average time to download the 500MB file. In my experience, the size of the file doesn’t matter too much. Obviously, smaller files will download quicker but will still download slower if the $ProgressPreference
variable is set to it’s default value.
Between PowerShell 5.1 and 7.x – the issue seems to be resolved and it no longer lags behind when attempting to download files.
What better way to make your current scripts run a bit quicker? Just toss in $ProgressPreference = 'SilentlyContinue'
before your Invoke-WebRequest
commands. Simply turning that progress bar off and you can see a 90ish% improvement.