Foreach-Object vs Foreach循环的运行时

时间:2016-09-22 09:27:58

标签: powershell

我想要对我的脚本执行一个进度条,但后来我需要一定数量的文件夹。

之间是否存在显着的运行时差异:

Get-ChildItem $path -Directory | ForEach-Object {
    #do work
}

$folders = Get-ChildItem $path -Directory
foreach($folder in $folders){
    #do work
}

然后我可以使用$folders.Count作为我的文件夹总数。我不知道如何使用foreach-object循环。

3 个答案:

答案 0 :(得分:5)

是的,存在性能差异。 foreachForEach-Object快,但需要更多内存,因为所有项目($folders)都必须在内存中。 ForEach-Object在通过管道时一次处理一个项目,因此它的内存占用量较小,但不如foreach快。

See also

答案 1 :(得分:3)

您可以自己检查:

Measure-Command {
    1..100000 | ForEach-Object $_
}

1.17s

Measure-Command {
    foreach ($i in (1..100000))
    {
    $i
    }
}

0.15s

答案 2 :(得分:2)

管道设计用于在物品出现时立即处理物品,因此在管道输送时,列表的整个长度都是未知的。

Get-ChildItem $path -Directory | ForEach {
    # PROCESSING STARTS IMMEDIATELY
    # LENGTH IS NOT KNOWN
}
  • 优势:处理立即开始,没有延迟构建列表。
  • 缺点:列表长度在完全处理之前是未知的

另一方面,将列表分配给变量会在此时构建整个列表,如果列表包含大量项目或构建速度很慢,则可能需要花费大量时间,例如,如果它是一个包含许多嵌套子目录或慢速网络目录的目录。

# BUILD THE ENTIRE LIST AND ASSIGN IT TO A VARIABLE
$folders = Get-ChildItem $path -Directory
# A FEW MOMENTS/SECONDS/MINUTES/HOURS LATER WE CAN PROCESS IT
ForEach ($folder in $folders) {
    # LENGTH IS KNOWN: $folders.count
}
  • 构建列表+ ForEach语句的优点:花费的总时间较少,因为在每个项目上处理{ }块不是调用而使用管道调用它就像一个函数或scriptblock,这种调用开销在PowerShell中非常大。
  • 缺点:列表赋值语句中的初始延迟可能非常大