diff --git a/Chronometer/Classes/Chronometer.ps1 b/Chronometer/Classes/Chronometer.ps1 index fe867df..37eed40 100644 --- a/Chronometer/Classes/Chronometer.ps1 +++ b/Chronometer/Classes/Chronometer.ps1 @@ -3,18 +3,26 @@ class Chronometer [hashtable]$FileMap = @{} $Breakpoint = @() - [void]AddBreakpoint([string[]]$Path) + [void]AddBreakpoint([string[]]$Path, [int[]]$LineNumber) { foreach($file in (Resolve-Path $Path -ea 0)) { $script = [MonitoredScript]@{Path=$file.Path} $lines = $script.SetScript($file) + if($LineNumber -ne $null) + { + $bpLine = $LineNumber + } + else + { + $bpLine = (1..$lines) + } $this.fileMap[$file.Path] = $script $breakpointParam = @{ Script = $file - Line = (1..$lines) + Line = $bpLine Action = {[ScriptProfiler]::RecordExecution( $_) } } $this.breakPoint += Set-PSBreakpoint @breakpointParam @@ -42,6 +50,10 @@ class Chronometer [MonitoredScript[]] GetResults() { + foreach($node in $this.FileMap.Values) + { + $node.PostProcessing() + } return $this.FileMap.Values } } diff --git a/Chronometer/Classes/MonitoredScript.ps1 b/Chronometer/Classes/MonitoredScript.ps1 index c2c04d7..e85acf6 100644 --- a/Chronometer/Classes/MonitoredScript.ps1 +++ b/Chronometer/Classes/MonitoredScript.ps1 @@ -46,4 +46,36 @@ class MonitoredScript $this.lastRecord = $record $this.lastNode = $node } + + [void] PostProcessing() + { + $this.lastNode = $null + $this.ExecutionTime = 0 + foreach($node in $this.line) + { + $command = $node.text -replace '\s','' + + switch -Regex ($command) + { + '^}$|^}#|^$' { + if($node.HitCount -eq 0) + { + $node.HitCount = $this.lastNode.HitCount + } + $node.Milliseconds = 0 + $node.Average = 0 + $this.lastNode = $node + } + '^{$|^{#}' { + $node.Milliseconds = 0 + $node.Average = 0 + $this.lastNode = $node + } + default { + $this.lastNode = $node + } + } + $this.ExecutionTime += $node.Milliseconds + } + } } \ No newline at end of file diff --git a/Chronometer/Public/Get-Chronometer.ps1 b/Chronometer/Public/Get-Chronometer.ps1 index bc95fa2..c13c51f 100644 --- a/Chronometer/Public/Get-Chronometer.ps1 +++ b/Chronometer/Public/Get-Chronometer.ps1 @@ -15,6 +15,10 @@ function Get-Chronometer [string[]] $Path, + # Line numbers within the script file to measure + [int[]] + $LineNumber = $null, + # The script to start the scrupt or execute other commands [alias('Script','CommandScript')] [scriptblock] @@ -24,7 +28,7 @@ function Get-Chronometer $Chronometer = [Chronometer]::New() Write-Verbose "Setting breapoints" - $Chronometer.AddBreakpoint($Path) + $Chronometer.AddBreakpoint($Path,$LineNumber) if($Chronometer.breakPoint -ne $null) { diff --git a/README.md b/README.md index 791061f..540fa0f 100644 --- a/README.md +++ b/README.md @@ -2,24 +2,35 @@ A module for measuring performance of Powershell scripts, one line at a time ## Project status -Experimental. Just a working idea at the moment. Functions and argument names are still up in the air. Also don't consider it stable or tested. Use at your own risk. +Preview release. The core logic is fleshed out but more testing is needed. # Getting started ## Prerequirements You need to have Powershell 5.0 or newer. This module uses classes. ## Installing Chronometer -Place the Chronometer folder into your `$PSModulePath`. I will publish to the Powershell Gallery once the project is more stable. +This is published in the Powershell Gallery + + Install-Module Chronometer ## Basic usage Provide a script file and a command to execute. $path = myscript.ps1 $Chronometer = Get-Chronometer -Path $path -Script {. .\myscript.ps1} - $Chronometer | % tostring | Format-Chronometer + $Chronometer | Format-Chronometer -The user experience is important to me but I am working on the core logic right now. I will loop back to make it more intuitive and simple to use. ## Things to know The `Path` can be any ps1 and the script can run any command. Ideally, you would either execute the script or load the script and execute a command inside it. +Here is a more complex example: + + $script = ls C:\workspace\PSGraph\PSGraph -Recurse -Filter *.ps1 + $Chronometer = @{ + Path = $script.fullname + Script = {Invoke-Pester C:\workspace\PSGraph} + } + $results = Get-Chronometer @Chronometer + $results | Format-Chronometer + diff --git a/Tests/Unit.Tests.ps1 b/Tests/Unit.Tests.ps1 index 3d2b475..71f832d 100644 --- a/Tests/Unit.Tests.ps1 +++ b/Tests/Unit.Tests.ps1 @@ -17,6 +17,17 @@ Describe "Basic unit tests" -Tags Build { $results = Get-Chronometer -Path $PSScriptRoot\..\ScratchFiles\example.ps1 -Script {. "$PSScriptRoot\..\ScratchFiles\example.ps1"} $results | Should Not BeNullOrEmpty } + + it "Executes a script with linenumbers and gives results" { + # Get-Chronometer -Path ScratchFiles\example.ps1 -Script {"Test"} + $params = @{ + Path = "$PSScriptRoot\..\ScratchFiles\example.ps1" + Script = {. "$PSScriptRoot\..\ScratchFiles\example.ps1"} + LineNumber = 2,3,5,6 + } + $results = Get-Chronometer @params + $results | Should Not BeNullOrEmpty + } } Context "Function: Format-Chronometer" {