Invoke-Command 比命令本身更快?
Invoke-Command faster than the command itself?
我试图衡量一些在 PowerShell 中写入文件的方法。毫无疑问,但我不明白为什么下面的第一个 Measure-Command
语句比第二个语句执行时间更长。
它们是相同的,但在第二个中我写了一个脚本块发送到 Invoke-Command
而在第一个中我只 运行 命令。
我能找到的所有关于 Invoke-Command
速度的信息都是关于远程处理的。
这个块大约需要 4 秒:
Measure-Command {
$stream = [System.IO.StreamWriter] "$PSScriptRoot\t.txt"
$i = 0
while ($i -le 1000000) {
$stream.WriteLine("This is the line number: $i")
$i++
}
$stream.Close()
} # takes 4 sec
下面这段代码完全相同,但写在传递给 Invoke-Command
的脚本块中,大约需要 1 秒:
Measure-Command {
$cmdtest = {
$stream = [System.IO.StreamWriter] "$PSScriptRoot\t2.txt"
$i = 0
while ($i -le 1000000) {
$stream.WriteLine("This is the line number: $i")
$i++
}
$stream.Close()
}
Invoke-Command -ScriptBlock $cmdtest
} # Takes 1 second
这怎么可能?
事实证明,根据 PowerShell 团队成员在 this related GitHub issue 上的反馈,问题更普遍地与 (隐式)点源(例如直接调用表达式)与子作用域中的 运行,例如使用 &
,调用运算符,或者,在手头的情况下,使用 Invoke-Command -ScriptBlock
.
运行 在子作用域中避免了在(隐式)点源时执行的变量查找。
因此,从 Windows PowerShell v5.1 / PowerShell Core 6.2 开始,您可以通过简单地加速 无副作用 表达式在子作用域中通过 & { ... }
调用它们(有点违反直觉,因为创建新作用域涉及 额外工作 ):
也就是说,此优化可用于不希望(直接)修改调用方变量的表达式。
以下使用 foreach
表达式循环 100 万次 (1e6
) 的简化代码演示了这一点:
# REGULAR, direct invocation of an expression (a `foreach` statement in this case),
# which is implicitly DOT-SOURCED
(Measure-Command { $result = foreach ($n in 1..1e6) { $n } }).TotalSeconds
# OPTIMIZED invocation in CHILD SCOPE, using & { ... }
# 10+ TIMES FASTER.
(Measure-Command { $result = & { foreach ($n in 1..1e6) { $n } } }).TotalSeconds
我试图衡量一些在 PowerShell 中写入文件的方法。毫无疑问,但我不明白为什么下面的第一个 Measure-Command
语句比第二个语句执行时间更长。
它们是相同的,但在第二个中我写了一个脚本块发送到 Invoke-Command
而在第一个中我只 运行 命令。
我能找到的所有关于 Invoke-Command
速度的信息都是关于远程处理的。
这个块大约需要 4 秒:
Measure-Command {
$stream = [System.IO.StreamWriter] "$PSScriptRoot\t.txt"
$i = 0
while ($i -le 1000000) {
$stream.WriteLine("This is the line number: $i")
$i++
}
$stream.Close()
} # takes 4 sec
下面这段代码完全相同,但写在传递给 Invoke-Command
的脚本块中,大约需要 1 秒:
Measure-Command {
$cmdtest = {
$stream = [System.IO.StreamWriter] "$PSScriptRoot\t2.txt"
$i = 0
while ($i -le 1000000) {
$stream.WriteLine("This is the line number: $i")
$i++
}
$stream.Close()
}
Invoke-Command -ScriptBlock $cmdtest
} # Takes 1 second
这怎么可能?
事实证明,根据 PowerShell 团队成员在 this related GitHub issue 上的反馈,问题更普遍地与 (隐式)点源(例如直接调用表达式)与子作用域中的 运行,例如使用 &
,调用运算符,或者,在手头的情况下,使用 Invoke-Command -ScriptBlock
.
运行 在子作用域中避免了在(隐式)点源时执行的变量查找。
因此,从 Windows PowerShell v5.1 / PowerShell Core 6.2 开始,您可以通过简单地加速 无副作用 表达式在子作用域中通过 & { ... }
调用它们(有点违反直觉,因为创建新作用域涉及 额外工作 ):
也就是说,此优化可用于不希望(直接)修改调用方变量的表达式。
以下使用 foreach
表达式循环 100 万次 (1e6
) 的简化代码演示了这一点:
# REGULAR, direct invocation of an expression (a `foreach` statement in this case),
# which is implicitly DOT-SOURCED
(Measure-Command { $result = foreach ($n in 1..1e6) { $n } }).TotalSeconds
# OPTIMIZED invocation in CHILD SCOPE, using & { ... }
# 10+ TIMES FASTER.
(Measure-Command { $result = & { foreach ($n in 1..1e6) { $n } } }).TotalSeconds