PowerShellPerformance/What_Is_The_Fastest_Way_To_Filter.benchmark.ps1

#requires -Module Benchpress

$valueList = 1..10000
$linqWhere = [Func[object,bool]]{param($_) $_ -gt 1000}
$whereGt1000 = { $_ -gt 1000 } 

Measure-Benchmark -GroupName "Filtering Values" -RepeatCount 10 -Technique @{
    "ForEach Loop" = {
        foreach ($v in $valueList) { if ($v -gt 1000) { $v } }
    }
    "Where-Object Script (Positional)" = {
        $valueList | Where-Object $whereGt1000
    }
    "Pipe to ScriptBlock" = {
        $valueList | & { process { if ($_ -gt 1000) { $_ } } }
    }
    "Operator Filter (Assumed Array)" = {
        # VERY DANGEROUS if $valueList isn't already typed as an array, it will
        # return $true/$false instead of acting as a filter on single objects
        $valueList -gt 1000
    }
    "Operator Filter (Explicit Array)" = {
        # Safe for arrays or single values
        @($valueList) -gt 1000
    }
    ".Where Method" = {
        $valueList.Where({$_ -gt 1000})
    }
    "Linq.Enumerable::Where" = {
        [System.Linq.Enumerable]::Where($valueList, $linqWhere)
    }
}


$objectList = foreach ($v in 1..100000) { [pscustomobject]@{Value=$v} }

Measure-Benchmark -GroupName "Filtering by Property Values" -RepeatCount 10 -Technique @{
    "ForEach Loop" = {
        foreach ($o in $objectList) { if ($o.Value -gt 1000) { $o } }
    }
    "Where-Object Property (Positional)" = {
        $objectList | Where-Object Value -GT 1000
    }
    "Pipe to ScriptBlock" = {
        $objectList | & { process { if ($_.Value -gt 1000) { $_ } } }
    }
    ".Where Method" = {
        $objectList.Where({$_.Value -gt 1000})
    }
}

$IsOdd = { process { if ($_ % 2) { $_ }  } } 
filter IsOdd { if ($_ % 2) { $_ }  } 
Measure-Benchmark -GroupName 'Filtering a Pipeline' -Technique @{
    "InlineScriptBlock" = {
        1..10 | & { process { if ($_ % 2) { $_ }  } }
    }
    ScriptBlockVariable = { 
        1..10 | 
            & $IsOdd 
    }
    'DotInline' = {
        1..10 | . { process { if ($_ % 2) { $_ }  } }
    }
    'DotScriptBlockVariable' = {
        1..10 | . $IsOdd
    }
    Filter = {
        1..10 | isOdd        
    }
    WhereObject = {
        1..10 | ? $IsOdd
    }
}