在 PowerShell 中计时命令的执行
有没有一种简单的方法可以在 PowerShell 中计时命令的执行时间,例如 Linux 中的“time”命令?
我想出了这个:
$s=Get-Date; .\do_something.ps1 ; $e=Get-Date; ($e - $s).TotalSeconds
但我想要一些更简单的东西,比如
time .\do_something.ps1
Is there a simple way to time the execution of a command in PowerShell, like the 'time' command in Linux?
I came up with this:
$s=Get-Date; .\do_something.ps1 ; $e=Get-Date; ($e - $s).TotalSeconds
But I would like something simpler like
time .\do_something.ps1
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
只是从答案中提到的任何性能测量命令得出(错误的)结论。除了查看(自定义)函数或命令的裸调用时间之外,还应该考虑许多陷阱。
斯约梅尔软件
我个人认为“Sjoemelsoftware”并不总是故意创建来欺骗测试结果,而是可能源于适应实际情况类似于如下所示的测试用例。
例如,使用列出的性能测量命令,语言集成查询 (LINQ)(1) 通常被认为是完成某件事的快速方法,而且通常是这样,但当然并非总是如此!与本机 PowerShell 命令相比,任何测量到速度提高了 40 倍或以上的人都可能错误地测量或得出错误的结论。
关键是一些 .Net 类(如 LINQ)使用 延迟评估< /a> (也称为延迟执行(2))。这意味着当将表达式分配给变量时,它几乎立即看起来已完成,但实际上它还没有处理任何内容!
假设您 dot-source 你的<代码>。 ,它具有 PowerShell 或更复杂的 Linq 表达式(为了便于解释,我已将表达式直接嵌入到
Measure-Command
中):.\Dosomething.ps1命令 结果很明显,后面的 Linq 命令比第一个 PowerShell 命令快大约 40 倍。不幸的是,事情没有那么简单...
让我们显示结果:
正如预期的那样,结果是相同的,但如果您密切注意,您会发现显示时间要长得多
$Linq
结果然后是$PowerShell
结果。让我们通过检索结果对象的属性来具体测量一下:
检索
$Linq
的属性花费了大约90 倍的时间对象,然后是$PowerShell
对象,而那只是一个对象!还要注意另一个陷阱,如果您再次执行此操作,某些步骤可能会比以前快得多,这是因为某些表达式已被缓存。
最重要的是,如果您想比较两个函数之间的性能,您需要在您的使用案例中实现它们,从新的 PowerShell 会话开始,并根据完整解决方案的实际性能得出结论。
(1) 有关 PowerShell 和 LINQ 的更多背景和示例,我推荐这个站点:使用 LINQ 的高性能 PowerShell
(2) 我认为这两个概念之间存在细微差别,因为延迟计算的结果是在需要时计算的,与延迟执行< /strong>结果是在系统空闲时计算的
Just a word on drawing (incorrect) conclusions from any of the performance measurement commands referred to in the answers. There are a number of pitfalls that should taken in consideration aside from looking to the bare invocation time of a (custom) function or command.
Sjoemelsoftware
Personally, I think that "Sjoemelsoftware" is not always deliberately created to cheat test results but might originate from accommodating practical situation that are similar to test cases as shown below.
As an example, using the listed performance measurement commands, Language Integrated Query (LINQ)(1), is often qualified as the fasted way to get something done and it often is, but certainly not always! Anybody who measures a speed increase of a factor 40 or more in comparison with native PowerShell commands, is probably incorrectly measuring or drawing an incorrect conclusion.
The point is that some .Net classes (like LINQ) using a lazy evaluation (also referred to as deferred execution(2)). Meaning that when assign an expression to a variable, it almost immediately appears to be done but in fact it didn't process anything yet!
Let presume that you dot-source your
. .\Dosomething.ps1
command which has either a PowerShell or a more sophisticated Linq expression (for the ease of explanation, I have directly embedded the expressions directly into theMeasure-Command
):The result appears obvious, the later Linq command is a about 40 times faster than the first PowerShell command. Unfortunately, it is not that simple...
Let's display the results:
As expected, the results are the same but if you have paid close attention, you will have noticed that it took a lot longer to display the
$Linq
results then the$PowerShell
results.Let's specifically measure that by just retrieving a property of the resulted object:
It took about a factor 90 longer to retrieve a property of the
$Linq
object then the$PowerShell
object and that was just a single object!Also notice an other pitfall that if you do it again, certain steps might appear a lot faster then before, this is because some of the expressions have been cached.
Bottom line, if you want to compare the performance between two functions, you will need to implement them in your used case, start with a fresh PowerShell session and base your conclusion on the actual performance of the complete solution.
(1) For more background and examples on PowerShell and LINQ, I recommend tihis site: High Performance PowerShell with LINQ
(2) I think there is a minor difference between the two concepts as with lazy evaluation the result is calculated when needed as apposed to deferred execution were the result is calculated when the system is idle
是的。
请注意,Measure-Command 的一个小缺点是您看不到
stdout
输出。[更新,感谢@JasonMArcher]您可以通过将命令输出传输到写入主机的某个命令行开关来解决此问题,例如
Out-Default
,因此它变成:查看输出的另一种方法是使用 .NET
Stopwatch
类,如下所示:Yup.
Note that one minor downside of
Measure-Command
is that you see nostdout
output.[Update, thanks to @JasonMArcher] You can fix that by piping the command output to some commandlet that writes to the host, e.g.
Out-Default
so it becomes:Another way to see the output would be to use the .NET
Stopwatch
class like this:您还可以从历史记录中获取最后一个命令,并从其
StartExecutionTime
中减去其EndExecutionTime
。You can also get the last command from history and subtract its
EndExecutionTime
from itsStartExecutionTime
.使用
Measure-Command
示例
通过到
Out-Host
的管道,您可以查看命令的输出,即否则由
Measure-Command
消耗。Use
Measure-Command
Example
The pipe to
Out-Host
allows you to see the output of the command, which isotherwise consumed by
Measure-Command
.简单
然后可以使用
你可能想要调整输出
Simples
then can use as
You may want to tweak the output
这是我编写的一个函数,其工作方式与 Unix
time
命令类似:来源:https://gist.github.com/bender-the-greatest/741f696d965ed9728dc6287bdd336874
Here's a function I wrote which works similarly to the Unix
time
command:Source: https://gist.github.com/bender-the-greatest/741f696d965ed9728dc6287bdd336874
一种更受 PowerShell 启发的方式来访问您关心的属性的值:
如 Measure-Command 返回 TimeSpan 对象。
注意:TimeSpan 对象还具有双精度型 TotalMilliseconds(例如上面我的例子中的 4.7322 TotalMilliseconds),这可能对您有用。就像 TotalSeconds、TotalDays 等。
A more PowerShell inspired way to access the value of properties you care about:
As Measure-Command returns a TimeSpan object.
note: The TimeSpan object also has TotalMilliseconds as a double (such as 4.7322 TotalMilliseconds in my case above) which might be useful to you. Just like TotalSeconds, TotalDays, etc.
到目前为止,所有答案都达不到提问者(和我)通过简单地在命令行开头添加“time”来计时命令的愿望。相反,它们都需要将命令括在方括号 (
{}
) 中以形成一个块。这是一个简短的函数,其工作方式更像 Unix 上的time
:All the answers so far fall short of the questioner's (and my) desire to time a command by simply adding "time " to the start of the command line. Instead, they all require wrapping the command in brackets (
{}
) to make a block. Here is a short function that works more liketime
on Unix:使用秒表并格式化经过时间:
使用示例
Using Stopwatch and formatting elapsed time:
Usage Samples
例如
for instance
在 PowerShell 中创建一个
time
命令,用于测量其他命令的执行时间1- 通过运行以下命令打开您的 PowerShell 配置文件:
2- 如果该配置文件不存在,使用以下方法创建一个:
3- 将以下函数添加到您的 PowerShell 配置文件中:
4- 保存更改并关闭文件。
现在,
时间< /code> 命令在任何新的 PowerShell 会话中全局可用
输出:
Create a
time
command in PowerShell that measures the execution time of other commands1- Open your PowerShell profile by running:
2- If the profile doesn't exist, create one using:
3- Add the following function to your PowerShell profile:
4- Save the changes and close the file.
Now,
time
command is available globally within any new PowerShell sessionsOUTPUT:
使用
Measure-Command
测量命令持续时间Out-Default
将命令输出到控制台(interval).ToString()
以显示时间通用格式$args -join ' '
和Invoke-Expression
运行 argcode $profile
中以永久添加别名"`"a
在命令完成时发出蜂鸣声默认
"c"
Use
Measure-Command
to measure command durationOut-Default
to output command to console(interval).ToString()
to show time in common format$args -join ' '
andInvoke-Expression
to run the argcode $profile
to add the alias permanently"`"a
to beep when the command is finishedThe default
"c"