Answers:
我只是对我所知道的四个选项做了一些测试。
Measure-Command {$(1..1000) | Out-Null}
TotalMilliseconds : 76.211
Measure-Command {[Void]$(1..1000)}
TotalMilliseconds : 0.217
Measure-Command {$(1..1000) > $null}
TotalMilliseconds : 0.2478
Measure-Command {$null = $(1..1000)}
TotalMilliseconds : 0.2122
## Control, times vary from 0.21 to 0.24
Measure-Command {$(1..1000)}
TotalMilliseconds : 0.2141
因此,我建议您使用除Out-Null
开销之外的任何内容。对我来说,下一个重要的事情就是可读性。我有点喜欢重定向到$null
并设置为等于$null
自己自己。我曾经更喜欢将强制转换为[Void]
,但是在浏览代码或为新用户浏览时可能无法理解。
我想我稍微喜欢将输出重定向到$null
。
Do-Something > $null
编辑
在stej再次发表评论之后,我决定对管道进行更多测试,以更好地隔离浪费输出的开销。
这是一些使用简单的1000对象管道的测试。
## Control Pipeline
Measure-Command {$(1..1000) | ?{$_ -is [int]}}
TotalMilliseconds : 119.3823
## Out-Null
Measure-Command {$(1..1000) | ?{$_ -is [int]} | Out-Null}
TotalMilliseconds : 190.2193
## Redirect to $null
Measure-Command {$(1..1000) | ?{$_ -is [int]} > $null}
TotalMilliseconds : 119.7923
在这种情况下,Out-Null
开销约为60%,开销> $null
约为0.3%。
附录2017-10-16:我最初忽略Out-Null
了使用-inputObject
参数的另一个选项。使用此开销似乎消失了,但是语法不同:
Out-Null -inputObject ($(1..1000) | ?{$_ -is [int]})
现在,使用简单的100对象管道进行一些测试。
## Control Pipeline
Measure-Command {$(1..100) | ?{$_ -is [int]}}
TotalMilliseconds : 12.3566
## Out-Null
Measure-Command {$(1..100) | ?{$_ -is [int]} | Out-Null}
TotalMilliseconds : 19.7357
## Redirect to $null
Measure-Command {$(1..1000) | ?{$_ -is [int]} > $null}
TotalMilliseconds : 12.8527
这里又有Out-Null
大约60%的开销。而> $null
开销大约为4%。每个测试之间的数字有所不同(我分别跑了5次并选择了中间位置)。但是我认为这表明了不使用的明显原因Out-Null
。
Out-Null
可能是开销。但是..如果将一个对象传递到Out-Null
0.076毫秒,恕我直言,对于脚本语言来说,它仍然是非常好的:)
我意识到这是一个旧线程,但是对于那些接受@JasonMArcher上面接受的答案为事实的人,我感到惊讶的是它没有得到纠正,我们许多人已经知道很多年了,实际上这是PIPELINE增加了延迟,而与是否它是否为零。实际上,如果您运行下面的测试,您会很快看到对[void]和$ void =的相同“快速”转换,多年来我们都认为它更快,实际上只是很慢,而实际上您可以添加任何流水线。换句话说,只要您通过管道传输任何内容,就不使用无效值的整个规则就会变成垃圾。
证明,下面列表中的最后3个测试。可怕的无效值是32339.3792毫秒,但是等等-强制转换为[void]有多快?34121.9251毫秒?!?WTF?这些是我系统上的REAL#,实际上转换为VOID较慢。= $ null怎么样?34217.685ms .....仍然很慢!因此,如最后三个简单测试所示,在许多情况下,已经使用了管道时,Out-Null实际上更快。
那么,为什么呢?简单。一直到向零输出的管道变慢是一种幻觉。但是,“向任何东西滑动”是比较慢的,我们不是已经通过基本逻辑知道了吗?我们可能还不知道慢得多,但是如果可以避免的话,这些测试肯定可以说明使用管道的成本。而且,我们并不是真的100%错了,因为有非常少的虚假情况是真实的情况。什么时候?添加Out-Null时,将添加仅管道活动。换句话说....一个简单命令的原因,例如$(1..1000)| 如上所示,Out-Null显示为true。
如果您只是将额外的管道添加到Out-String到上面的每个测试中,则#会发生根本变化(或仅粘贴下面的代码),并且如您所见,在许多情况下,Out-Null实际上变得更快:
$GetProcess = Get-Process
# Batch 1 - Test 1
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$GetProcess | Out-Null
}
}).TotalMilliseconds
# Batch 1 - Test 2
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
[void]($GetProcess)
}
}).TotalMilliseconds
# Batch 1 - Test 3
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$null = $GetProcess
}
}).TotalMilliseconds
# Batch 2 - Test 1
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$GetProcess | Select-Object -Property ProcessName | Out-Null
}
}).TotalMilliseconds
# Batch 2 - Test 2
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
[void]($GetProcess | Select-Object -Property ProcessName )
}
}).TotalMilliseconds
# Batch 2 - Test 3
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$null = $GetProcess | Select-Object -Property ProcessName
}
}).TotalMilliseconds
# Batch 3 - Test 1
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$GetProcess | Select-Object -Property Handles, NPM, PM, WS, VM, CPU, Id, SI, Name | Out-Null
}
}).TotalMilliseconds
# Batch 3 - Test 2
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
[void]($GetProcess | Select-Object -Property Handles, NPM, PM, WS, VM, CPU, Id, SI, Name )
}
}).TotalMilliseconds
# Batch 3 - Test 3
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$null = $GetProcess | Select-Object -Property Handles, NPM, PM, WS, VM, CPU, Id, SI, Name
}
}).TotalMilliseconds
# Batch 4 - Test 1
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$GetProcess | Out-String | Out-Null
}
}).TotalMilliseconds
# Batch 4 - Test 2
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
[void]($GetProcess | Out-String )
}
}).TotalMilliseconds
# Batch 4 - Test 3
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$null = $GetProcess | Out-String
}
}).TotalMilliseconds
Out-Null
管道的问题,因此,显示管道开销的最佳方法是在Out-Null
有或没有管道的情况下进行调用。在我的系统上,对于10,000次迭代,我的速度为0.576秒,Out-Null -InputObject $GetProcess
而的为5.656秒(慢近10倍)$GetProcess | Out-Null
。
[void]
,并$null
仍执行好过| Out-Null
。我知道这是因为管线,并且增量在以后的批次中缩小了,但是在我的机器Out-Null
上,这两个批次中的执行速度都不快。
[void]
并且由于$null
会比| Out-Null
- 表现更好|
。尝试Out-Null -InputObject (expression)
进行比较。
还有Out-Null
cmdlet,您可以在管道中使用该cmdlet,例如Add-Item | Out-Null
。
NAME
Out-Null
SYNOPSIS
Deletes output instead of sending it to the console.
SYNTAX
Out-Null [-inputObject <psobject>] [<CommonParameters>]
DETAILED DESCRIPTION
The Out-Null cmdlet sends output to NULL, in effect, deleting it.
RELATED LINKS
Out-Printer
Out-Host
Out-File
Out-String
Out-Default
REMARKS
For more information, type: "get-help Out-Null -detailed".
For technical information, type: "get-help Out-Null -full".
[void]
即使Out-Null解决方案看起来更“强大”,我也将切换到该版本。
[void]
看起来很清晰(我没有说过powershellish),您会在该行的开头看到该行中没有输出。因此,这是另一个优势,如果您大循环进行出零,则性能可能会成为问题;)
我个人使用它... | Out-Null
是因为,正如其他人评论的那样,与... > $null
和相比,它看起来更像是“ PowerShellish”方法[void] ...
。 $null = ...
正在利用一个特定的自动变量,并且很容易被忽略,而其他方法通过附加的语法使其变得显而易见,即您打算丢弃表达式的输出。因为... | Out-Null
并且... > $null
在表达式的结尾,我认为他们有效地交流了“把到目前为止所做的一切都丢掉了”,而且... # | Out-Null
与放置之前$null =
或[void]
之后相比,您可以出于调试目的(例如)将它们注释掉更容易该表达式确定执行后发生的情况。
但是,让我们看一个不同的基准:不是执行每个选项所花费的时间,而是弄清楚每个选项所执行的花费的时间。在与没有使用PowerShell甚至根本没有脚本经验的同事一起工作的环境中,我倾向于尝试编写脚本,以使几年后甚至不了解他们所使用语言的人都可以拥有一个脚本。因为他们可能不得不支持或替换它,所以有机会弄清楚它在做什么。直到现在,我从来没有将它作为使用其他方法的理由,但是想象一下您处于那个位置,并且您使用help
命令或您喜欢的搜索引擎来尝试找出什么Out-Null
做。您会立即获得有用的结果,对吗?现在尝试做同样的[void]
和$null =
。不是那么容易,是吗?
当然,与理解脚本的整体逻辑相比,抑制值的输出是一个非常小的细节,并且您只能在尝试为代码编写良好代码的能力之前,对代码进行“精简”。新手的阅读能力……不是很好。我的观点是,它可能是一些谁在PowerShell中流利甚至不熟悉[void]
,$null =
等等,只是因为那些可以更快地执行或花费更少的击键类型,并不意味着他们是做的最好的方法您正在尝试做的事情,仅仅是因为一种语言为您提供了古怪的语法,并不意味着您应该使用它而不是更清晰,更广为人知的语言。*
*我想这Out-Null
很清楚而且众所周知,我不知道是什么$true
。无论您何时键入代码或执行时间如何,无论您觉得哪种方式最清晰,并且对于以后的代码阅读者和编辑者(包括您自己),最容易使用的,这是我建议您使用的选项。