New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
measure-command should be capable of streaming output either to the host or downstream cmdlets #2289
Comments
I don't think doing that by default is a good idea. Writing objects to the pipe while measuring would change how that script block performs. You might think we could turn off the stopwatch while writing objects to downstream pipes, but downstream code that isn't measured could still have a significant impact on the code being measured. Format and output is not always efficient. It may allocate a lot of memory. We could trigger garbage collection in ways that make measuring the performance of the script block harder. Given this, I think it's reasonable to require |
All that is true and why we wouldn't want to change the default behavior but it seems reasonable to have a SWITCH parameter would would enable this. |
@be5invis it would be great if you can provide more details, i.e. the motivation example. My best guess is that request is not about a downstream pipeline, but about native commands. Measure-Command { ping ya.ru } currently, the output of ping is collected and not passed down. The reason I think that's the request is because the original title said STDOUT and STDERR, so I immediately think about native executables. UPD: note that stderr is already behaves as requested, and the behavior for stdout can be achived with Measure-Command { ping ya.ru | Write-Host } |
So something like a |
Measure-Command takes ValueFromPipeline. So the general approach is: 1,2,3,4,5 | where { largescriptblock } | foreach {...}
1,2,3,4,5 | measure-command -MeasureVariable outArray -PipeExpression { where {largescriptblock} } | foreach {...} |
A vote to including the output as a standard operation. I'd suggest we're over-focusing on the timing, and losing the context of what's being attempted. I've got a series of commands I'd like to time, because "something isn't looking right". If I don't have the output, I can't tell what's happening that might have caused a delay. While I appreciate measuring might further add to the amount of time, it's what we need to be useful. Please don't make me do some fancy stream output. Really, I just want my command to be wrapped with a start time, and end time, with the execution time. Perhaps put the timings in a green color. |
Guys, you must be joking. Without showing the stdout and stderr while measuring, this command is largely useless. For a moment I rejoiced I finally found a way to measure a command execution time native to Windows, only to find that I cannot use it. I need to see the output of a command. I can hardly think of use cases where I would want to suppress stdout and stderr. This is just madness. Please, bring the output back to screen. |
A better idea is I've sent a PR to make it easier to find there: MicrosoftDocs/PowerShell-Docs#4783 |
A better default is to dispaly output on screen without the need so specify |
Unfortunately, piping the output strips color :( |
This is not just about interactive use cases, there's a use case for using Can we just have a |
I vote for a new switch that would result in getting the exact same output (color included ;-) ) as the raw command being timed. Changing the default behavior is probably a bad idea, for backwards-compatibility's sake. |
That's a fairly sensible suggestion. I don't see why we can't |
Just to be clear, |
Hmm. I think it'd be best if it either:
|
@vexx32 that all seems pretty complicated compared to just saving the output to a variable no? Measure-Command { $data = Invoke-MyTest } vs $result = Measure-Command -PassThru { Invoke-MyTest }
$data = $result.Data
$result.Duration
Why wouldn't the |
This is an exhaustive answer why we should not implement this request. We can always get the result with: Measure-Command { $data = Invoke-MyTest } |
"Getting the result" (pipeline data) is not the same as "getting the same results" (display). |
No, we can't always do that. This may be possible in most scripts, and maybe even every script you wrote personally, but it's definitely not possible in all scripts. I very recently ran a complex script that processed GB of data through the pipeline. It is simply not possible to save the pipeline output in a variable first, because it would exceed the machine's memory. That is what actually led me to this issue. A minor downside is also that it's hard to statically analyze, e.g. VS Code will complain that The argument that downstream consumers can slow down the pipeline is a valid one of course, and it can mean that the measured time does not represent only time spent in the script block, but also time spent by the script block waiting because of back pressure. But you don't know if that is actually going to have an impact. For example, in most cases, the "downstream consumer" will just be the host formatting + output, or maybe some light processing of the data. If what we are measuring involves IO, that time will be negligible, and as a user I would like to have the option to ignore it and tell PowerShell to just pipe it through anyway instead of requiring me to rewrite the whole script to not use pipelines (which again, may not even be possible due to memory constraints). Ideally of course there would be a way to get the real time spent by the script block. I don't know if this is technically possible, but maybe it is, if the Since I mentioned Unix's Answering to more questions from above:
Yes, in some cases that's exactly what I want to do. Imagine there's a cmdlet that does REST API calls with
I think that would be sensible, similar to how |
But then that's part of the test, so why wouldn't that be included in the script block? Why is it necessary to do this: Measure-Command { Invoke-LongCommand } | Select-Object -First 1 Instead of: Measure-Command { Invoke-LongCommand | Select-Object -First 1 } |
You can easily do that in an example code snippet on GitHub, but that doesn't mean it's easily possible in a complex script. We could be talking about dozens of layers of function calls across multiple files, where somewhere there's the |
You wouldn't need to restructure anything, just wrap it in a script block: Measure-Command {
& {
# complicated code here
} | Select-Object -First 1
}
|
@felixfbecker |
Just going to add my voice to the conversation, I would also love a
I was surprised it didn't already have this functionality, I guess I am more familiar with |
If the comparison is to the |
yes / yes ;-) |
I'm also going to have to agree that this is a missed feature of The problem that I run into is that I want to know how long a command is going to take including how long it takes to render output if that command is going to do that. It's important to be able to capture reality with In my mind, when I run this:
I should get comparable time to doing this:
And I don't. I get a difference of two orders of magnitude on my system (~60ms vs ~2800ms) because I shouldn't have to modify my command to make that work, either, because then I have no way to know if it's performing as it is because that's accurate or because I modified it. You can easily modify it in such a way that it greatly increases the time, after all. For example, there's a huge difference between these because of the number of pipelines constructed:
The second command takes twice as long on my system (~2700ms vs ~4300ms). "Okay," you say, "so always use the first pattern." Well, if you're using a statement like
That adds 10,000 pipeline constructions and teardowns to the loop. A loop that previously had no pipelines in it. Yes, I can just use |
@iSazonov That's possible. Based on a quick reading, though, that looks like it's going to be more useful for second order analysis while I'm mostly interested in first order or top level analysis? My argument is that |
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. |
1 similar comment
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. |
This issue has been marked as "No Activity" as there has been no activity for 6 months. It has been closed for housekeeping purposes. |
No description provided.
The text was updated successfully, but these errors were encountered: