functions/performance/Measure-PSMDCommand.ps1
function Measure-PSMDCommand { <# .SYNOPSIS Measures command performance with consecutive tests. .DESCRIPTION This function measures the performance of a scriptblock many consective times. Warning: Running a command repeatedly may not yield reliable information, since repeated executions may benefit from caching or other performance enhancing features, depending on the script content. This is best suited for measuring the performance of tasks that will later be run repeatedly as well. It also is useful for mitigating local performance fluctuations when comparing performances. .PARAMETER ScriptBlock The scriptblock whose performance is to be measure. .PARAMETER Iterations How many times should this performance test be repeated. .PARAMETER TestSet Accepts a hashtable, mapping a name to a specific scriptblock to measure. This will generate a result grading the performance of the various sets offered. .EXAMPLE PS C:\> Measure-PSMDCommand -ScriptBlock { dir \\Server\share } -Iterations 100 This tries to use Get-ChildItem on a remote directory 100 consecutive times, then measures performance and reports common performance indicators (Average duration, Maximum, Minimum, Total) #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ParameterSetName = 'Script')] [scriptblock] $ScriptBlock, [int] $Iterations = 1, [Parameter(Mandatory = $true, ParameterSetName = 'Set')] [hashtable] $TestSet ) Process { #region Running an individual testrun if ($ScriptBlock) { [System.Collections.ArrayList]$results = @() $count = 0 while ($count -lt $Iterations) { $null = $results.Add((Measure-Command -Expression $ScriptBlock)) $count++ } $measured = $results | Measure-Object -Maximum -Minimum -Average -Sum -Property Ticks [pscustomobject]@{ PSTypeName = 'PSModuleDevelopment.Performance.TestResult' Results = $results.ToArray() Max = (New-Object System.TimeSpan($measured.Maximum)) Sum = (New-Object System.TimeSpan($measured.Sum)) Min = (New-Object System.TimeSpan($measured.Minimum)) Average = (New-Object System.TimeSpan($measured.Average)) } } #endregion Running an individual testrun #region Performing a testset if ($TestSet) { $setResult = @{ } foreach ($testName in $TestSet.Keys) { $setResult[$testName] = Measure-PSMDCommand -ScriptBlock $TestSet[$testName] -Iterations $Iterations } $fastestResult = $setResult.Values | Sort-Object Average | Select-Object -First 1 $finalResult = foreach ($setName in $setResult.Keys) { $resultItem = $setResult[$setName] [pscustomobject]@{ PSTypeName = 'PSModuleDevelopment.Performance.TestSetItem' Name = $setName Efficiency = $resultItem.Average.Ticks / $fastestResult.Average.Ticks Average = $resultItem.Average Result = $resultItem } } $finalResult | Sort-Object Efficiency } #endregion Performing a testset } } |