PowerShellPerformance/multithreading.benchmark.ps1
#requires -Module Benchpress # Define the Number of Threads here!!! $threads = 10 # Using this to be sure no test failed $resultGrid = [System.Collections.Generic.List[object]]::new() $ran = [random]::new() $items = 100000 $testArray = while($items--) { [pscustomobject]@{ FirstValue = $ran.Next() SecondValue = $ran.Next() } } $average = [System.Linq.Enumerable]::Average( [int[]] $testArray.FirstValue ) $ThreadJobAvailable = Get-Module ThreadJob -ListAvailable $ParallelAvailable = $PSVersionTable.PSVersion -ge [version] '7.0' [ref] $Reference = 0 $groupSize = [math]::Ceiling($testArray.Count / $threads) $chunks = $testArray | Group-Object -Property { [math]::Floor($Reference.Value++ / $groupSize) } $action = { param($array, $average) foreach($i in $array) { if($i.FirstValue -le $average -and $i.SecondValue % 2) { $i } } } $expectedCount = $( foreach($chunk in $chunks) { & $action $chunk.Group $average } ).Count $resultObject = { param($TestName, $TestCount, $ExpectedCount) [pscustomobject]@{ Test = $TestName Count = $TestCount Status = ('FAILED', 'PASSED')[$Testcount -eq $ExpectedCount] } } $techniques = @{ "Start-Job" = { $jobs = foreach($chunk in $chunks) { Start-Job -ScriptBlock $action -ArgumentList $chunk.Group, $average } $resultJob = Receive-Job $jobs -Wait -AutoRemoveJob $hash = @{ TestName = 'Job' TestCount = $resultJob.Count ExpectedCount = $expectedCount } $thisTest = & $resultObject @hash } "Runspace" = { $RunspacePool = [runspacefactory]::CreateRunspacePool(1, $threads) $RunspacePool.Open() $runspace = foreach($chunk in $chunks) { $params = @{ array = $chunk.Group average = $average } $ps = [powershell]::Create().AddScript($action).AddParameters($params) $ps.RunspacePool = $RunspacePool @{ Instance = $ps Handle = $ps.BeginInvoke() } } $resultRunspace = foreach($r in $runspace) { $r.Instance.EndInvoke($r.Handle) } $RunspacePool.Dispose() $hash = @{ TestName = 'Runspace' TestCount = $resultRunspace.Count ExpectedCount = $expectedCount } $thisTest = & $resultObject @hash } } if($ThreadJobAvailable) { $techniques["Start-ThreadJob"] = { $jobs = foreach($chunk in $chunks) { Start-ThreadJob -ScriptBlock $action -ArgumentList $chunk.Group, $average -ThrottleLimit $threads } $resultThreadJob = Receive-Job $jobs -Wait -AutoRemoveJob $hash = @{ TestName = 'ThreadJob' TestCount = $resultThreadJob.Count ExpectedCount = $expectedCount } $thisTest = & $resultObject @hash } } if($ParallelAvailable) { $techniques["ForEach-Object -Parallel"] = { $resultParallel = $chunks | ForEach-Object -Parallel { foreach($i in $_.Group) { if($i.FirstValue -le $using:average -and $i.SecondValue % 2) { $i } } } -ThrottleLimit $threads $hash = @{ TestName = 'Parallel' TestCount = $resultParallel.Count ExpectedCount = $expectedCount } $thisTest = & $resultObject @hash } } Measure-Benchmark -GroupName "Multi-Threading" -RepeatCount 3 -Technique $techniques |