You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Write-Progress drops updates if the calls happen too quickly in succession #18848
Note: This is a regression from Windows PowerShell and affects both the Minimal and Classic views (selectable via $PSStyle.Progress.View)
$arr=1..10$arr|ForEach-Object {
[int] $percentComplete= ($_/$arr.Count) *100Write-Progress-Activity Test -Status "$percentComplete% complete"-PercentComplete $percentComplete# !! Without sleeping for a while, the progress display stops updating after the FIRST call.# Start-Sleep -Milliseconds 200
}
Start-Sleep5# Ensure that the progress bar stays visible for a while.
Expected behavior
The progress bar should show 100% and stay visible for 5 seconds.
Actual behavior
The progress bar shows 10% - that is, only the first call took effect.
I think you're referring to this change #2822 which was taken awhile back. Basically progress isn't updated except once every 200ms. WinPS had the problem that it would update progress EVERY time an update was available. The time rendering to the console impacted performance (classic examples is invoke-webrequest to download a file took much longer). So I think this is considered by-design,.
It's understandable to want to throttle progress updates so as not to unduly impact overall performance.
However, I don't think it is acceptable to ignore subsequent updates.
Whatever the last update was in the 200-msec. time window should render.
Consider a long-running task with progress reports whose timing is highly variable / unpredictable, especially during parallel processing (ForEach-Object -Parallel):
Say there are bursts of updates followed by long periods of non-updates.
If the bursts significantly meant to advance the progress display (in small increments), the long period of non-updates will present a distorted view.
This API is flexible enough to avoid such effects. The script developer just needs to use this API correctly. There are three phases - initialization, loop update and finalization. In this example, you need to execute "Complete" after the loop to display the correct state.
We could make PowerShell smarter, but I don't see the point. I consider this API obsolete to invest in it. It would make sense to create something more modern, productive and convenient. All we need is desire and approval :-)
Ilya (@iSazonov), the example scenario in my previous comment illustrates that the API is not flexible enough - calling "Complete" in the middle of a long-running operation is obviously both unexpected and inappropriate.
Optimizing is a laudable goal, as long as it doesn't get in the way of the user's intent.
Here, it clearly does.
I haven't looked into the technical challenges, but to me the current behavior is unacceptable.
If a modern API can remedy this, all the better - assuming it ever sees the light of day.
I was talking about a common script that works correctly - init-update-in-loop-fin.
If we're talking about the body of the loop, as indicated, it makes no sense to update the output on the screen every "microsecond". This not only creates a performance problem but also violates the very concept of "Progress Bar".
I've noticed that many native tools don't actually clear out progress info once complete (and we'd have to change the code to show the last progress update). So that could help with this, but would have its own dissenters.
I've noticed that many native tools don't actually clear out progress info once complete (and we'd have to change the code to show the last progress update). So that could help with this, but would have its own dissenters.
I've noticed that many native tools don't actually clear out progress info once complete (and we'd have to change the code to show the last progress update). So that could help with this, but would have its own dissenters.
What kind of script example are you referring to?
Not any script example, I'm referring to native commands that emit their own custom progress. They tend to keep the last progress on the screen rather than clearing it.
Michael Klement (@mklement0) I believe individual cmdlets that are part of PowerShell have also had improvements to how often they write progress. However, the perf fix was general such that poorly written scripts and cmdlets would also not incur a perf impact that the author or even user may not have known about.
It may be possible to cache the last progress update (rather than discard it) and on every 200ms if the last progress rendered isn't the same as the last progress written, then update without incurring a regression in perf. I believe the significant perf impact previous was the time taken to render on the console so doing a bit of progress record comparison, even frequently, might be ok.
If we talk exclusively about this optimization (although I think we should start the discussion with the progressbar concept), I do not think that something can be done there without significant cost and loss of optimization.
We do three expensive things at each step:
Creating ProgressRecord
Writing this ProgressRecord to the engine buffer with preprocessing
Rendering
Now the optimization cuts off steps 2 and 3. To store the "last" ProgressRecord, we will have to do step two and move the thinning to this level. That is, we lose optimization and add complexity.
If we start with the progressbar concept, however, we can get an implementation that eliminates losses not only in step 2 and 3, but in step one as well!
If we talk about the progress bar concept, this is the correct PowerShell as an idea.
If we look PowerShell stream fundamentals we see 5 PowerShell Streams (Output, Error, Warning, Verbose, Debug) and there is no progress bar. Why? Because progress bar is ephemeral thing, it is psevdo-stream.
We could think of it as sounds or voice messages.
The main point is that this information does not intersect with real streams in any way, is not accumulated anywhere, and is not stored anywhere. All relevant information must be directed to the actual PowerShell streams.
If this antipode to real streams did not exist it should have been created!
Earlier I have already formulated this concept as:
The only purpose of the progress bar, as the name says, is to inform the interactive user that the long process is ongoing.
Keys here are "inform", "interactive", "long". It is not to follow these key principles then problems are inevitable.
The PowerShell implementation of this concept is done in the spirit of PowerShell, implying that it is done as cmdlets.
But then we see problems in this implementation (much of this is due to a deviation from key principles):
it is very expensive, i.e. the cost of creating and displaying the progress bar is too high and can exceed the cost of the main work.
it is too vague, which provokes developers to misuse it in violation of the concept, i.e. they try to display significant information in the progress bar, when it should be directed to one (or more) real PowerShell streams.
Can PowerShell have a less expensive implementation? Sure.
Could PowerShell be smarter, save the developer from unnecessary work and tricks? Sure.
I think the request is reasonable from a user perspective, but also agree with Ilya (@iSazonov) (as I've also poked around the Progress code) that the current design of the code doesn't lend itself for enabling these types of changes easily without risk of regression/impact nor is it more critical than spending time fixing other functional issues.
Perhaps we should think about and adopt the concept that will allow us to simplify the code and at the same time increase the possibilities of customization.
I was installing an update on Exchange Servers today and there is an instructive progress bar - "this operation will take a few minutes", "this operation will take a long time", etc. - no dots, blinks, flickers or anything else superfluous. Definitely they know how to do things right.
That makes sense, Ilya (@iSazonov), but it seems that the only thing needed for that kind of abstract display is to fix the regression from Windows PowerShell (simply don't display a bar if -PercentComplete isn't used, as previously noted).
As for the optimization: note that my proposal was - expressed in terms of the 3-step model you describe above - to only do step 1 (repeatedly) in a 200-msec. window and then do steps 2 and 3 only once, at the end of that window - but perhaps that indeed complicates things too much, given that that requires the rendering to happen asynchronously.
given that that requires the rendering to happen asynchronously.
I was hoping this was possible, but it turns out that the progress bar display is done synchronously and directly from the runspaces.
Moreover, there is no classic dedicated UI thread, the main thread is conhost (UI) and at the same time runs the main runspace.
I think some MSFT teams (as well as other developers) would breathe freer and get rid of headaches if pwsh had a dedicated thread for UI and runspaces were detached from threads. (We can only guess how many resources this eats up in Office365.)
For example, the Exchange Server team migrated code to managed and more so to asynchronous TAP, but obviously other than pwsh related code.
This seems to be a relic of the old development environment limitations.
Reacted by Michael Klement, HRXN and Darren Kattan
microsoft-github-policy-service commented on Nov 15, 2023
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
microsoft-github-policy-service commented on Nov 15, 2023
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
microsoft-github-policy-service commented on Nov 22, 2023
Hi. I can see Write-Progress is a lightweight progress indicator, thus the update limiter. I run into this problem too. I have a script that checks ~150 items for changes. If there are no changes, it will go through all of them in about 1 second. But if an item has changes, it can take 15 to 20 seconds to process it. So when scanning items, the current displayed item is "always" wrong if it needs to process something. This can lead to much confusion and panic.
My workaround is simple. I added a second progress bar with another -Id, that is displayed only when an item needs to be processed. Clean, fast and simple.
PS. It would be nice to have this update limiter documented in the Write-Progress documentation and propose a second progress bar as a workaround.
Activity
SteveL-MSFT commentedon Dec 28, 2022
I think you're referring to this change #2822 which was taken awhile back. Basically progress isn't updated except once every 200ms. WinPS had the problem that it would update progress EVERY time an update was available. The time rendering to the console impacted performance (classic examples is
invoke-webrequestto download a file took much longer). So I think this is considered by-design,.mklement0 commentedon Dec 28, 2022
Steve Lee (@SteveL-MSFT):
It's understandable to want to throttle progress updates so as not to unduly impact overall performance.
However, I don't think it is acceptable to ignore subsequent updates.
Consider a long-running task with progress reports whose timing is highly variable / unpredictable, especially during parallel processing (
ForEach-Object -Parallel):iSazonov commentedon Dec 29, 2022
This API is flexible enough to avoid such effects. The script developer just needs to use this API correctly. There are three phases - initialization, loop update and finalization. In this example, you need to execute "Complete" after the loop to display the correct state.
We could make PowerShell smarter, but I don't see the point. I consider this API obsolete to invest in it. It would make sense to create something more modern, productive and convenient. All we need is desire and approval :-)
mklement0 commentedon Dec 29, 2022
Ilya (@iSazonov), the example scenario in my previous comment illustrates that the API is not flexible enough - calling "Complete" in the middle of a long-running operation is obviously both unexpected and inappropriate.
mklement0 commentedon Dec 29, 2022
Optimizing is a laudable goal, as long as it doesn't get in the way of the user's intent.
Here, it clearly does.
I haven't looked into the technical challenges, but to me the current behavior is unacceptable.
If a modern API can remedy this, all the better - assuming it ever sees the light of day.
mklement0 commentedon Dec 29, 2022
And come to think of it: using
-Completeddoesn't display the correct state, it hides the - potentially outdated - progress bar.iSazonov commentedon Dec 29, 2022
I was talking about a common script that works correctly - init-update-in-loop-fin.
If we're talking about the body of the loop, as indicated, it makes no sense to update the output on the screen every "microsecond". This not only creates a performance problem but also violates the very concept of "Progress Bar".
SteveL-MSFT commentedon Dec 29, 2022
I've noticed that many native tools don't actually clear out progress info once complete (and we'd have to change the code to show the last progress update). So that could help with this, but would have its own dissenters.
iSazonov commentedon Dec 29, 2022
What kind of script example are you referring to?
SteveL-MSFT commentedon Dec 29, 2022
Not any script example, I'm referring to native commands that emit their own custom progress. They tend to keep the last progress on the screen rather than clearing it.
9 remaining items
SteveL-MSFT commentedon Jan 6, 2023
Michael Klement (@mklement0) I believe individual cmdlets that are part of PowerShell have also had improvements to how often they write progress. However, the perf fix was general such that poorly written scripts and cmdlets would also not incur a perf impact that the author or even user may not have known about.
It may be possible to cache the last progress update (rather than discard it) and on every 200ms if the last progress rendered isn't the same as the last progress written, then update without incurring a regression in perf. I believe the significant perf impact previous was the time taken to render on the console so doing a bit of progress record comparison, even frequently, might be ok.
iSazonov commentedon Jan 6, 2023
If we talk exclusively about this optimization (although I think we should start the discussion with the progressbar concept), I do not think that something can be done there without significant cost and loss of optimization.
We do three expensive things at each step:
Now the optimization cuts off steps 2 and 3. To store the "last" ProgressRecord, we will have to do step two and move the thinning to this level. That is, we lose optimization and add complexity.
If we start with the progressbar concept, however, we can get an implementation that eliminates losses not only in step 2 and 3, but in step one as well!
iSazonov commentedon Jan 6, 2023
If we talk about the
progress bar concept, this is the correct PowerShell as an idea.If we look PowerShell stream fundamentals we see 5 PowerShell Streams (Output, Error, Warning, Verbose, Debug) and there is no progress bar. Why? Because progress bar is ephemeral thing, it is psevdo-stream.
We could think of it as sounds or voice messages.
The main point is that this information does not intersect with real streams in any way, is not accumulated anywhere, and is not stored anywhere. All relevant information must be directed to the actual PowerShell streams.
If this antipode to real streams did not exist it should have been created!
Earlier I have already formulated this concept as:
Keys here are "inform", "interactive", "long". It is not to follow these key principles then problems are inevitable.
The PowerShell implementation of this concept is done in the spirit of PowerShell, implying that it is done as cmdlets.
But then we see problems in this implementation (much of this is due to a deviation from key principles):
Can PowerShell have a less expensive implementation? Sure.
Could PowerShell be smarter, save the developer from unnecessary work and tricks? Sure.
SteveL-MSFT commentedon Jan 9, 2023
I think the request is reasonable from a user perspective, but also agree with Ilya (@iSazonov) (as I've also poked around the Progress code) that the current design of the code doesn't lend itself for enabling these types of changes easily without risk of regression/impact nor is it more critical than spending time fixing other functional issues.
iSazonov commentedon Jan 9, 2023
Perhaps we should think about and adopt the concept that will allow us to simplify the code and at the same time increase the possibilities of customization.
I was installing an update on Exchange Servers today and there is an instructive progress bar - "this operation will take a few minutes", "this operation will take a long time", etc. - no dots, blinks, flickers or anything else superfluous. Definitely they know how to do things right.
mklement0 commentedon Jan 9, 2023
That makes sense, Ilya (@iSazonov), but it seems that the only thing needed for that kind of abstract display is to fix the regression from Windows PowerShell (simply don't display a bar if
-PercentCompleteisn't used, as previously noted).As for the optimization: note that my proposal was - expressed in terms of the 3-step model you describe above - to only do step 1 (repeatedly) in a 200-msec. window and then do steps 2 and 3 only once, at the end of that window - but perhaps that indeed complicates things too much, given that that requires the rendering to happen asynchronously.
iSazonov commentedon Jan 10, 2023
I was hoping this was possible, but it turns out that the progress bar display is done synchronously and directly from the runspaces.
Moreover, there is no classic dedicated UI thread, the main thread is conhost (UI) and at the same time runs the main runspace.
I think some MSFT teams (as well as other developers) would breathe freer and get rid of headaches if pwsh had a dedicated thread for UI and runspaces were detached from threads. (We can only guess how many resources this eats up in Office365.)
For example, the Exchange Server team migrated code to managed and more so to asynchronous TAP, but obviously other than pwsh related code.
This seems to be a relic of the old development environment limitations.
microsoft-github-policy-service commentedon Nov 15, 2023
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
microsoft-github-policy-service commentedon Nov 15, 2023
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
microsoft-github-policy-service commentedon Nov 15, 2023
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
microsoft-github-policy-service commentedon Nov 22, 2023
This issue has been marked as "No Activity" as there has been no activity for 6 months. It has been closed for housekeeping purposes.
seppo498573908457 commentedon Jun 11, 2026
Hi. I can see Write-Progress is a lightweight progress indicator, thus the update limiter. I run into this problem too. I have a script that checks ~150 items for changes. If there are no changes, it will go through all of them in about 1 second. But if an item has changes, it can take 15 to 20 seconds to process it. So when scanning items, the current displayed item is "always" wrong if it needs to process something. This can lead to much confusion and panic.
My workaround is simple. I added a second progress bar with another -Id, that is displayed only when an item needs to be processed. Clean, fast and simple.
PS. It would be nice to have this update limiter documented in the Write-Progress documentation and propose a second progress bar as a workaround.