Powershell - Benchmark Command

Powershell comes with a cmdlet called "Measure-Command" that can execute a block of commands and measure how long it takes to run. It's analogous to the unix "time" command.

What if you want to run something a number of times and take the average?

Here's a powershell function to do just that:

function measure_runs {
    param (
        [int]$numberRuns = $(throw "numberRuns is required"),
        [ScriptBlock]$beforeRun = $null,
        [ScriptBlock]$run = {}
       )
 
    $times = @()
 
    for($i=1;$i -le $numberRuns;$i++) { 
        Write-Host -NoNewline ("[" + "{0,4}" -f $i + " / " + "{0,4}" -f $numberRuns + "] ")
 
        if($beforeRun -ne $null) {
            Write-Host -NoNewline ("(Preparing... ) ")
            &$beforeRun | Out-Null
        }
 
        Write-Host -NoNewline ("Running...")
 
        $seconds = (Measure-Command $run).TotalSeconds
        $times += $seconds
 
        Write-Host -NoNewline (" {0,14:N4} seconds" -f $seconds)
 
        Write-Host
    }
 
    $times | Measure-Object -average | Select-Object Average
}

Specify the number of runs, the command to run and optionally a command to run before each run to be measured. (The before command is not included in the time.)

measure_runs -numberRuns N -run { cmd } [-beforeRun { cmd }]

Example:

PS D:\Development\jboss-seam-2.1.2> measure_runs -numberRuns 5 -beforeRun { ant clean } -run { ant }
[   1 /    5] (Preparing... ) Running...        34.1149 seconds
[   2 /    5] (Preparing... ) Running...        34.4194 seconds
[   3 /    5] (Preparing... ) Running...        34.5866 seconds
[   4 /    5] (Preparing... ) Running...        34.5777 seconds
[   5 /    5] (Preparing... ) Running...        34.2238 seconds
 
Average
-------
34.38447462

The hardest part was figuring out how to supress the newline when outputting so that the progress could be displayed incrementally.
The default Write-Output cmdlet doesn't let you do that, however the Write-Host cmdlet does using to "-noNewline" option.

No votes yet