Skip to content

Commit 1e4160a

Browse files
Add performance testing scripts for various PowerShell operations
1 parent 8885a34 commit 1e4160a

12 files changed

Lines changed: 521 additions & 0 deletions

guidance/Add-Array.ps1

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
$tests = @{
2+
'PowerShell Explicit Assignment' = {
3+
param($count)
4+
5+
$result = foreach ($i in 1..$count) {
6+
$i
7+
}
8+
$null = $result # just added for linter issues
9+
}
10+
'.Add(..) to List<T>' = {
11+
param($count)
12+
13+
$result = [Collections.Generic.List[int]]::new()
14+
foreach ($i in 1..$count) {
15+
$result.Add($i)
16+
}
17+
}
18+
'+= Operator to Array' = {
19+
param($count)
20+
21+
$result = @()
22+
foreach ($i in 1..$count) {
23+
$result += $i
24+
}
25+
}
26+
}
27+
28+
5kb, 10kb, 100kb | ForEach-Object {
29+
$groupResult = foreach ($test in $tests.GetEnumerator()) {
30+
$ms = (Measure-Command { & $test.Value -Count $_ }).TotalMilliseconds
31+
32+
[pscustomobject]@{
33+
CollectionSize = $_
34+
Test = $test.Key
35+
TotalMilliseconds = [math]::Round($ms, 2)
36+
}
37+
38+
[GC]::Collect()
39+
[GC]::WaitForPendingFinalizers()
40+
}
41+
42+
$groupResult = $groupResult | Sort-Object TotalMilliseconds
43+
$groupResult | Select-Object *, @{
44+
Name = 'RelativeSpeed'
45+
Expression = {
46+
$relativeSpeed = $_.TotalMilliseconds / $groupResult[0].TotalMilliseconds
47+
[math]::Round($relativeSpeed, 2).ToString() + 'x'
48+
}
49+
}
50+
}

guidance/Add-HashTable.ps1

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Adding 10000 items property-style
2+
Measure-Command {
3+
$HashProp = @{}
4+
1..10000 | ForEach-Object { $HashProp.$_ = $_ }
5+
}
6+
7+
# Adding 10000 items using the Add method
8+
Measure-Command {
9+
$HashMethod = @{}
10+
1..10000 | ForEach-Object { $HashMethod.Add($_, $_) }
11+
}
12+
13+
# Adding 10000 items dictionary-style
14+
Measure-Command {
15+
$HashDict = @{}
16+
1..10000 | ForEach-Object { $HashDict[$_] = $_ }
17+
}

guidance/Add-String.ps1

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
$tests = @{
2+
'StringBuilder' = {
3+
$sb = [System.Text.StringBuilder]::new()
4+
foreach ($i in 0..$args[0]) {
5+
$sb = $sb.AppendLine("Iteration $i")
6+
}
7+
$sb.ToString()
8+
}
9+
'Join operator' = {
10+
$string = @(
11+
foreach ($i in 0..$args[0]) {
12+
"Iteration $i"
13+
}
14+
) -join "`n"
15+
$string
16+
}
17+
'Addition Assignment +=' = {
18+
$string = ''
19+
foreach ($i in 0..$args[0]) {
20+
$string += "Iteration $i`n"
21+
}
22+
$string
23+
}
24+
}
25+
26+
10kb, 50kb, 100kb | ForEach-Object {
27+
$groupResult = foreach ($test in $tests.GetEnumerator()) {
28+
$ms = (Measure-Command { & $test.Value $_ }).TotalMilliseconds
29+
30+
[pscustomobject]@{
31+
Iterations = $_
32+
Test = $test.Key
33+
TotalMilliseconds = [math]::Round($ms, 2)
34+
}
35+
36+
[GC]::Collect()
37+
[GC]::WaitForPendingFinalizers()
38+
}
39+
40+
$groupResult = $groupResult | Sort-Object TotalMilliseconds
41+
$groupResult | Select-Object *, @{
42+
Name = 'RelativeSpeed'
43+
Expression = {
44+
$relativeSpeed = $_.TotalMilliseconds / $groupResult[0].TotalMilliseconds
45+
[math]::Round($relativeSpeed, 2).ToString() + 'x'
46+
}
47+
}
48+
}

guidance/Caller.ps1

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
function Invoke-Function4 {
2+
[CmdletBinding()]
3+
param()
4+
'In: ' + $MyInvocation.InvocationName
5+
$caller = (Get-PSCallStack)[1].Command
6+
'Caller: ' + $caller
7+
}
8+
9+
function Invoke-Function3 {
10+
[CmdletBinding()]
11+
param()
12+
'In: ' + $MyInvocation.InvocationName
13+
$caller = (Get-PSCallStack)[1].Command
14+
'Caller: ' + $caller
15+
Invoke-Function4
16+
}
17+
18+
function Invoke-Function2 {
19+
[CmdletBinding()]
20+
param()
21+
'In: ' + $MyInvocation.InvocationName
22+
$caller = (Get-PSCallStack)[1].Command
23+
'Caller: ' + $caller
24+
Invoke-Function3
25+
}
26+
27+
function Invoke-Function1 {
28+
[CmdletBinding()]
29+
param()
30+
'In: ' + $MyInvocation.InvocationName
31+
Get-PSCallStack
32+
$caller = (Get-PSCallStack)[1].Command
33+
'Caller: ' + $caller
34+
Invoke-Function2
35+
}
36+
37+
# Test the functions
38+
Invoke-Function1

guidance/ClassExtension.ps1

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
class C {
2+
[string]$Name
3+
4+
C([string]$Name) {
5+
$this.Name = $Name
6+
}
7+
8+
[string]GetInfo() {
9+
return "Name: $($this.Name)"
10+
}
11+
}
12+
13+
class B : C {
14+
[int]$Age
15+
16+
B([string]$Name, [int]$Age) : base($Name) {
17+
$this.Age = $Age
18+
}
19+
20+
[string]GetInfo() {
21+
# Cast $this to the parent class (C) to call its GetInfo()
22+
return "$(([C]$this).GetInfo()), Age: $($this.Age)"
23+
}
24+
}
25+
26+
class A : B {
27+
[string]$Role
28+
29+
A([string]$Name, [int]$Age, [string]$Role) : base($Name, $Age) {
30+
$this.Role = $Role
31+
}
32+
33+
[string]GetInfo() {
34+
# Cast $this to B to call B’s GetInfo(), which itself calls C’s GetInfo()
35+
return "$(([B]$this).GetInfo()), Role: $($this.Role)"
36+
}
37+
}
38+
39+
# Creating and testing an instance
40+
$person = [A]::new('John Doe', 30, 'Manager')
41+
$person.GetInfo()

guidance/Loops.ps1

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
$ranGen = New-Object System.Random
2+
$RepeatCount = 10000
3+
4+
'Basic for-loop = {0}ms' -f (Measure-Command -Expression {
5+
for ($i = 0; $i -lt $RepeatCount; $i++) {
6+
$Null = $ranGen.Next()
7+
}
8+
}).TotalMilliseconds
9+
10+
'Wrapped in a function = {0}ms' -f (Measure-Command -Expression {
11+
function Get-RandNum_Core {
12+
param ($ranGen)
13+
$ranGen.Next()
14+
}
15+
16+
for ($i = 0; $i -lt $RepeatCount; $i++) {
17+
$Null = Get-RandNum_Core $ranGen
18+
}
19+
}).TotalMilliseconds
20+
21+
'For-loop in a function = {0}ms' -f (Measure-Command -Expression {
22+
function Get-RandNum_All {
23+
param ($ranGen)
24+
for ($i = 0; $i -lt $RepeatCount; $i++) {
25+
$Null = $ranGen.Next()
26+
}
27+
}
28+
29+
Get-RandNum_All $ranGen
30+
}).TotalMilliseconds

guidance/Out-Null.ps1

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
$tests = @{
2+
'Assign to $null' = {
3+
$arrayList = [System.Collections.ArrayList]::new()
4+
foreach ($i in 0..$args[0]) {
5+
$null = $arraylist.Add($i)
6+
}
7+
}
8+
'Cast to [void]' = {
9+
$arrayList = [System.Collections.ArrayList]::new()
10+
foreach ($i in 0..$args[0]) {
11+
[void]$arraylist.Add($i)
12+
}
13+
}
14+
'Redirect to $null' = {
15+
$arrayList = [System.Collections.ArrayList]::new()
16+
foreach ($i in 0..$args[0]) {
17+
$arraylist.Add($i) > $null
18+
}
19+
}
20+
'Pipe to Out-Null' = {
21+
$arrayList = [System.Collections.ArrayList]::new()
22+
foreach ($i in 0..$args[0]) {
23+
$arraylist.Add($i) | Out-Null
24+
}
25+
}
26+
}
27+
28+
10kb, 50kb, 100kb | ForEach-Object {
29+
$groupResult = foreach ($test in $tests.GetEnumerator()) {
30+
$ms = (Measure-Command { & $test.Value $_ }).TotalMilliseconds
31+
32+
[pscustomobject]@{
33+
Iterations = $_
34+
Test = $test.Key
35+
TotalMilliseconds = [math]::Round($ms, 2)
36+
}
37+
38+
[GC]::Collect()
39+
[GC]::WaitForPendingFinalizers()
40+
}
41+
42+
$groupResult = $groupResult | Sort-Object TotalMilliseconds
43+
$groupResult | Select-Object *, @{
44+
Name = 'RelativeSpeed'
45+
Expression = {
46+
$relativeSpeed = $_.TotalMilliseconds / $groupResult[0].TotalMilliseconds
47+
[math]::Round($relativeSpeed, 2).ToString() + 'x'
48+
}
49+
}
50+
}

guidance/PSCallStack.ps1

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
function Invoke-Function4 {
2+
[CmdletBinding()]
3+
param()
4+
'In: ' + $MyInvocation.InvocationName
5+
Get-PSCallStack
6+
}
7+
8+
function Invoke-Function3 {
9+
[CmdletBinding()]
10+
param()
11+
'In: ' + $MyInvocation.InvocationName
12+
Get-PSCallStack
13+
Invoke-Function4
14+
}
15+
16+
function Invoke-Function2 {
17+
[CmdletBinding()]
18+
param()
19+
'In: ' + $MyInvocation.InvocationName
20+
Get-PSCallStack
21+
Invoke-Function3
22+
}
23+
24+
function Invoke-Function1 {
25+
[CmdletBinding()]
26+
param()
27+
"In: " + $MyInvocation.InvocationName
28+
Get-PSCallStack
29+
Invoke-Function2
30+
}
31+
32+
# Test the functions
33+
Invoke-Function1

guidance/PSCmdlet.ps1

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
function Invoke-Function4 {
2+
[CmdletBinding()]
3+
param()
4+
'4: ' + $MyInvocation.InvocationName
5+
$PSCmdlet | ConvertTo-Json
6+
}
7+
8+
function Invoke-Function3 {
9+
[CmdletBinding()]
10+
param()
11+
'3: ' + $MyInvocation.InvocationName
12+
$PSCmdlet | ConvertTo-Json
13+
Invoke-Function4
14+
}
15+
16+
function Invoke-Function2 {
17+
[CmdletBinding()]
18+
param()
19+
'2: ' + $MyInvocation.InvocationName
20+
$PSCmdlet | ConvertTo-Json
21+
Invoke-Function3
22+
}
23+
24+
function Invoke-Function1 {
25+
[CmdletBinding()]
26+
param()
27+
'1: ' + $MyInvocation.InvocationName
28+
$PSCmdlet | ConvertTo-Json
29+
Invoke-Function2
30+
}
31+
32+
# Test the functions
33+
Invoke-Function1

0 commit comments

Comments
 (0)