Last active
September 4, 2022 19:48
-
-
Save zett42/7dd95d4b37d35b00e1155646c2d43fdc to your computer and use it in GitHub Desktop.
Test performance of various ways to join arrays of objects on a given property in PowerShell
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MyObject1 { | |
[string] $Name | |
[int] $Foo | |
} | |
class MyObject2 { | |
[string] $Name | |
[int] $Bar | |
} | |
# Creates two related arrays of given size. | |
# 1st array contains objects of class MyObject1 with random $name property. | |
# 2nd array contains objects of class MyObject2, whose $name properties matches the name property of random elements from 1st array. | |
Function New-TestData( [int] $size ) { | |
Write-Host "Creating two arrays of $size objects..." | |
$array1 = foreach( $i in 0..($size - 1) ) { [MyObject1]@{ | |
#$array1 = foreach( $i in 0..($size -1 ) ) { [PSCustomObject]@{ | |
Name = [Guid]::NewGuid().ToString('n') | |
Foo = $i | |
}} | |
$rnd = [Random]::new() | |
$array2 = foreach( $i in 0..($size - 1) ) { [MyObject2]@{ | |
#$array2 = foreach( $i in 0..($size - 1) ) { [PSCustomObject]@{ | |
# Get name of random element from $df1 | |
Name = $array1[ $rnd.NextSingle() * ($array1.Count - 1) ].Name | |
Bar = $i + $size | |
}} | |
[PSCustomObject] @{ array1 = $array1; array2 = $array2 } | |
} | |
Function Write-TestResultOfRun( $duration, $joinedArray ) { | |
Write-Host "Run took $('{0:0.##} s' -f $duration.TotalSeconds)" | |
Write-Host "Joined count: $($joinedArray.Count)" | |
Write-Host "Some rows of joined objects:`n$($joinedArray[0..2] | Format-Table | Out-String)" | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$totalRuns = 10 | |
$dataSize = 1e5 | |
$durations = 1..$totalRuns | ForEach-Object { | |
Write-Host -ForegroundColor Green "----- Run $_ of $totalRuns -----" | |
Start-Job { | |
# From https://github.com/iRon7/Join-Object | |
Import-Module .\iron_join.psm1 | |
# In this gist | |
Import-Module .\_JoinPerfTestHelper.psm1 | |
$data = New-TestData $using:dataSize | |
Write-Host 'Joining...' | |
$duration = Measure-Command { | |
$joinedArray = Join-Object -LeftObject $data.array1 -RightObject $data.array2 -On Name -JoinType Inner | |
} | |
Write-TestResultOfRun $duration $joinedArray | |
$duration # To be captured in $durations | |
} | Receive-Job -Wait -AutoRemoveJob | |
} | |
"`nAVG: {0:0.##} s" -f ($durations | Measure-Object TotalSeconds -Average).Average |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Function Join-Enumerable{ | |
[CmdletBinding()] | |
param ( | |
[Parameter(Mandatory)] | |
[Collections.IEnumerable] $Left, | |
[Parameter(Mandatory)] | |
[Collections.IEnumerable] $Right, | |
[Parameter(Mandatory)] | |
$LeftKey, | |
[Parameter(Mandatory)] | |
$RightKey, | |
[Parameter(Mandatory)] | |
[scriptblock] $Result, | |
[Parameter()] | |
[switch] $NoEnumerate | |
) | |
if( $RightKey -isnot [scriptblock] ) { | |
$RightKey = [scriptblock]::Create( "`$args.{$RightKey}" ) | |
} | |
if( $LeftKey -isnot [scriptblock] ) { | |
$LeftKey = [scriptblock]::Create( "`$args.{$LeftKey}" ) | |
} | |
$enumerator = [Linq.Enumerable]::Join( $Left, $Right, | |
[Func[object, object]] $RightKey, | |
[Func[object, object]] $LeftKey, | |
[Func[object, object, object]] $Result ) | |
if( $NoEnumerate ) { | |
return , $enumerator # Outputs the enumerator itself | |
} | |
$enumerator # Enumerates and outputs each result element | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$totalRuns = 10 | |
$dataSize = 1e5 | |
$durations = 1..$totalRuns | ForEach-Object { | |
Write-Host -ForegroundColor Green "----- Run $_ of $totalRuns -----" | |
Start-Job { | |
# In this gist | |
Import-Module .\zett42_JoinEnumerable.psm1 | |
# In this gist | |
Import-Module .\_JoinPerfTestHelper.psm1 | |
$data = New-TestData $using:dataSize | |
Write-Host 'Joining...' | |
class MyJoinedObject { | |
[string] $Name | |
[int] $Foo | |
[int] $Bar | |
} | |
$duration = Measure-Command { | |
$joinedArray = Join-Enumerable -Left $data.array1 -Right $data.array2 -LeftKey Name -RightKey Name -Result { | |
[MyJoinedObject] @{ | |
#[PSCustomObject] @{ | |
Name = $args[0].Name | |
Foo = $args[0].Foo | |
Bar = $args[1].Bar | |
} | |
} | |
} | |
Write-TestResultOfRun $duration $joinedArray | |
$duration # To be captured in $durations | |
} | Receive-Job -Wait -AutoRemoveJob | |
} | |
"`nAVG: {0:0.##} s" -f ($durations | Measure-Object TotalSeconds -Average).Average |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment