Runtime of Foreach-Object vs Foreach loop

前端 未结 3 1537
被撕碎了的回忆
被撕碎了的回忆 2020-12-11 09:44

I want to do a progress bar of my script but then I need a total amount of folders.

Is there a significant runtime difference between:

Get-ChildItem          


        
相关标签:
3条回答
  • 2020-12-11 09:54

    Yes, there is a performance difference. foreach is faster than ForEach-Object, but requires more memory, because all items ($folders) must be in memory. ForEach-Object processes one item at a time as they're passed through the pipeline, so it has a smaller memory footprint, but isn't as fast as foreach.

    See also.

    0 讨论(0)
  • 2020-12-11 10:03

    Piping is designed to process items immediately as they appear so the entire length of the list is not known while it's being piped.

    Get-ChildItem $path -Directory | ForEach {
        # PROCESSING STARTS IMMEDIATELY
        # LENGTH IS NOT KNOWN
    }
    
    • Advantage: processing starts immediately, no delay to build the list.
    • Disadvantage: the list length is not known until it's fully processed

    On the other hand, assigning the list to a variable builds the entire list at this point, which can take an extremely large amount of time if the list contains lots of items or it's slow to build, for example, if it's a directory with lots of nested subdirectories, or a slow network directory.

    # 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
    }
    
    • Advantage of building the list + ForEach statement: overall time spent is less because processing { } block is not invoked on each item whereas with piping it is invoked like a function or scriptblock, and this invocation overhead is very big in PowerShell.
    • Disadvantage: the initial delay in the list assignment statement can be extremely huge
    0 讨论(0)
  • 2020-12-11 10:13

    You can check for yourself:

    Measure-Command {
        1..100000 | ForEach-Object $_
    }
    
    1.17s
    
    Measure-Command {
        foreach ($i in (1..100000))
        {
        $i
        }
    }
    
    0.15s
    
    0 讨论(0)
提交回复
热议问题