From ec38d169be983ad62178cb65f10d32eeb14d8ccc Mon Sep 17 00:00:00 2001 From: KevinMarquette Date: Thu, 2 Feb 2017 19:02:36 -0800 Subject: [PATCH] Added core functions and classes --- Chronometer/Classes/ScriptLine.ps1 | 40 +++++++++++++++++ Chronometer/Classes/ScriptProfiler.ps1 | 19 ++++++++ Chronometer/Public/Get-Chronometer.ps1 | 62 ++++++++++++++++++++++++++ 3 files changed, 121 insertions(+) create mode 100644 Chronometer/Classes/ScriptLine.ps1 create mode 100644 Chronometer/Classes/ScriptProfiler.ps1 create mode 100644 Chronometer/Public/Get-Chronometer.ps1 diff --git a/Chronometer/Classes/ScriptLine.ps1 b/Chronometer/Classes/ScriptLine.ps1 new file mode 100644 index 0000000..3962c1f --- /dev/null +++ b/Chronometer/Classes/ScriptLine.ps1 @@ -0,0 +1,40 @@ + +class ScriptLine +{ + [float] $Milliseconds = 0 + [float] $HitCount = 0 + [float] $Min = [float]::MaxValue + [float] $Max = [float]::MinValue + [float] $Average = 0 + [int] $LineNumber + [string] $Path + [string] $Text + + [void]AddExecutionTime([float]$Milliseconds) + { + $this.Milliseconds += $Milliseconds + $this.HitCount += 1 + $this.Average = $this.Milliseconds / $this.HitCount + + if($Milliseconds -lt $this.Min) + { + $this.Min = $Milliseconds + } + + if($Milliseconds -gt $this.Max) + { + $this.Max = $Milliseconds + } + } + + [string] ToString() + { + $values = @( + $this.Milliseconds + $this.HitCount + $this.Average + $this.Text + ) + return ("[{0:0000}ms,{1:0000},{2:0000}ms] {3}" -f $values) + } +} \ No newline at end of file diff --git a/Chronometer/Classes/ScriptProfiler.ps1 b/Chronometer/Classes/ScriptProfiler.ps1 new file mode 100644 index 0000000..7f6821e --- /dev/null +++ b/Chronometer/Classes/ScriptProfiler.ps1 @@ -0,0 +1,19 @@ +class ScriptProfiler { + + static [System.Collections.Queue] $Queue + static [System.Diagnostics.Stopwatch] $Timer + + static [void] Start() + { + [ScriptProfiler]::Queue = New-Object System.Collections.Queue + [ScriptProfiler]::Timer = [System.Diagnostics.Stopwatch]::StartNew() + } + + static [void] RecordExecution ([System.Management.Automation.LineBreakpoint]$InputObject) + { + [ScriptProfiler]::Queue.Enqueue(@{ + Breakpoint = $InputObject + ElapsedMilliseconds = [ScriptProfiler]::Timer.ElapsedMilliseconds + }) + } +} diff --git a/Chronometer/Public/Get-Chronometer.ps1 b/Chronometer/Public/Get-Chronometer.ps1 new file mode 100644 index 0000000..534a2b9 --- /dev/null +++ b/Chronometer/Public/Get-Chronometer.ps1 @@ -0,0 +1,62 @@ +function Get-Chronometer +{ + [CmdletBinding()] + param( + [string[]] + $Path, + + [scriptblock] + $CommandScript + ) + + $breakPoint = @() + $fileMap = @{} + + foreach($file in (Resolve-Path $Path)) + { + $fileMap[$file.Path] = @( Get-Content -Path $file | %{[ScriptLine]@{text=$_;path=$file.path}}) + + $lines = $fileMap[$file.Path].count + $breakPoint += Set-PSBreakpoint -Script $file -Line (1..$lines) -Action {[ScriptProfiler]::RecordExecution( $_) } + } + + [ScriptProfiler]::Start() + [void] $CommandScript.Invoke() + + Remove-PSBreakpoint $breakpoint + + #$fileMap | ConvertTo-Json + + + foreach($node in [ScriptProfiler]::Queue.GetEnumerator()) + { + $record = $fileMap[$node.Breakpoint.Script][$node.Breakpoint.Line-1] + $record.LineNumber = $node.Breakpoint.Line - 1 + + if($lastNode) + { + $duration = $node.ElapsedMilliseconds - $lastNode.ElapsedMilliseconds + } + else + { + $duration = $node.ElapsedMilliseconds + } + + + if($lastRecord) + { + $lastRecord.AddExecutionTime($duration) + } + + $lastRecord = $record + $lastNode = $node + } + + foreach($script in $fileMap.Keys) + { + foreach($line in $fileMap[$script]) + { + Write-Output $line + } + } +}