Average Rating:

4.00 by 2 users.

50 Downloads, 218 Views

2 Comment(s)

Measure-ScriptBlockAverageTime.ps1

By: Frank ERBLAND 22 Apr 2011 02:05 AM UTC in the category: Beginner Event 10

Tags:

Description:

This script measure the average time a scriptblock takes to execute.
It runs the scripblock n times and compute the average time with Measure-Command cmdlet.
It display a formal message according the asked time unit.
By default : It measures the scriptblock {Start-Sleep -Second 5}, 5 times, and shows
average result in milliseconds (with 5 digits after decimal point).
It also writes the result to the pipeline as an Microsoft.PowerShell.Commands.GenericMeasureInfo object.
Possible intermediate results in verbose mode and a progress bar.
##########################################################################################################
# Measure-ScriptBlockAverageTime.ps1
# Version: 1.0.0
# Date: 21/04/2011
# Author: Frank ERBLAND
# Object: The 2011 Scripting Games Beginner Event 10: Use PowerShell to Measure Time to Complete a Command
##########################################################################################################

<#

.SYNOPSIS
    Measure the average time a scriptblock takes to execute.
    
.DESCRIPTION
    This script measure the average time a scriptblock takes to execute.
    It runs the scripblock n times and compute the average time with Measure-Command cmdlet.
    It display a formal message according the asked time unit.
    By default : It measures the scriptblock {Start-Sleep -Second 5}, 5 times, and shows
    average result in milliseconds (with 5 digits after decimal point).
    It also writes the result to the pipeline.
    Possible intermediate results in verbose mode and a progress bar.
        
.PARAMETER ScriptBlock
    The target scripblock to execute and measure.
    
.PARAMETER ScriptLabel
    A label which describe the scriptblock object.

.PARAMETER Count
    The number of iteration for average computing.
    
.PARAMETER TimeUnit
    The time unit to express the result.
    Valid values: "Day","d","Hour","h","Minute","mn","Second","s","Millisecond","ms" (case-insensitive)
    
.PARAMETER Format
    The numeric format string such as "N2".
    For more information, see operator "-f" or .NET function "[String]::Format()" documentations.
    
.PARAMETER Progress
    Switch for displaying a progress bar (uses Write-Progress).
    
.EXAMPLE.
    Measure-ScriptBlockAverageTime.ps1
    Description
    ---------------------------------------------------------------
    Report the average time of 5 executions of the default scriptblock {Start-Sleep -Seconds 5}.
    A formal message is written to the console and the value is also passed to
    the pipeline for additionnal treatments.
    
.EXAMPLE.
    Measure-ScriptBlockAverageTime.ps1 -Verbose
    Description
    ---------------------------------------------------------------
    Report the average time of 5 executions of the default scriptblock and show intermediates results.
    
.EXAMPLE.
    Measure-ScriptBlockAverageTime.ps1 -ScriptBlock {Get-ChildItem d:\users\$env:USERNAME -recurse}
    -ScriptLabel "Parsing current user profile" -Count 10  -Format "N2" -TimeUnit "s" -Verbose -Progress
    Description
    ---------------------------------------------------------------
    Execute ten times the scriptblock {Get-ChildItem d:\users\$env:USERNAME -recurse} and show
    the average time it takes in seconds with 2 digits after the decimal point.
    It also show intermediate time results and a progress bar.

.INPUTS
    No pipeline input allowed.
    
.OUTPUTS
    System.Double, the average time in asked units. 

.LINK
    http://blogs.technet.com/b/heyscriptingguy/archive/2011/04/15/the-2011-scripting-games-beginner-event-10-use-powershell-to-measure-time-to-complete-a-command.aspx

#>

[CmdletBinding()]
Param(
    # ScriptBlock to measure
    [Parameter(Mandatory = $false)]
    [ScriptBlock] $ScriptBlock = {Start-Sleep -Seconds 5}
,
    # Script label for message output
    [Parameter(Mandatory = $false)]
    [String] $ScriptLabel = "5 seconds"
,
    # Number of iterations
    [Parameter(Mandatory = $false)]
    [Int] $Count = 5
,
    # Time unit to express the result
    [Parameter(Mandatory = $false)]
    [ValidateSet("Day","d","Hour","h","Minute","mn","Second","s","Millisecond","ms")]
    [String] $TimeUnit = "ms"
,
    # Numeric format string
    [Parameter(Mandatory = $false)]
    [String] $Format = "N5"
,
    # Switch Progress
    [Parameter(Mandatory = $false)]
    [Switch] $Progress
)

# ************************************************************************************
begin 
{
    # *********************************************************
    # Helper Function: Write-IterationProgress
    # Display a progress bar of the iterations.
    # Note : Operates only with -Progress switch.
    # *********************************************************

    function Write-IterationProgress([Int] $i)
    {
        if($Progress) {
            $params = @{
                Activity = "Measure-Command `"{0}`"" -f $ScriptLabel;
                Status = "Iteration {0} / {1} is running..." -f $i, $Count;
                PercentComplete = ($i-1)*100/$Count
            }
            Write-Progress @params
        }
    } ### End function Write-IterationProgress
    
    # Set $TimeSpanProperty to access the right TimeSpan object property.
    switch -regex ($TimeUnit)
    {
        # This comparison is case-insensitive
        "Day|d" {$TimeSpanProperty = "TotalDays"}
        "Hour|h" {$TimeSpanProperty = "TotalHours"}
        "Minute|mn" {$TimeSpanProperty = "TotalMinutes"}
        "Second|s" {$TimeSpanProperty = "TotalSeconds"}
        "Millisecond|ms" {$TimeSpanProperty = "TotalMilliseconds"}
    }
    
    # Set $TimeUnitLabel for a pretty console output.
    $TimeUnitLabel = $TimeSpanProperty.Substring(5).ToLower()


}

# ************************************************************************************
process 
{
    # Measure the time the scriptblock takes $Count times
    $Measures = (1..$Count) | ForEach-Object {
        Write-IterationProgress $_
        $Time = Measure-Command $ScriptBlock
        Write-Verbose ("Iteration time {0}/{1} : {2:$Format} {3}." -f $_, $Count, $Time.$TimeSpanProperty, $TimeUnitLabel)
        Write-Output $Time
    }
    
    # Compute the average time
    $Measure = $Measures | Measure-Object -Average -Property $TimeSpanProperty
}

# ************************************************************************************
end
{
    # Output result to the console
    Write-Host ("Average time of {0} runs of {1} is " -f $Count,$ScriptLabel) -NoNewline
    Write-Host ("{0:$Format}" -f $Measure.Average) -ForegroundColor Yellow -BackgroundColor Black -NoNewline
    Write-Host (" {0}." -f ($TimeSpanProperty -replace 'Total','').ToLower())

    # Output results to the pipeline for post-treatments
    Write-Output $Measure.Average
}

# ************************************************************************************
# End of script
# ************************************************************************************
Top

Comments:

4/23/2011 10:57 PM
Great job done on this. Possibly the only way to look into improving on this is using the "MEASURE-COMMAND" Cmdlet instead. Try it, you'll LIKE it ! :)
4/27/2011 8:18 PM
Thank's for your rating and comments, Sean ! I do my best...
But I do use Measure-Command, line149 ?!! I effectively like it, as always with PoSh !