Skip to content

Commit 7818776

Browse files
Improve performance of Get-GitHubContent (#232)
The call to `ConvertTo-SmarterObject` was adding a significant amount of time to the execution of Get-GitHubContent. ```powershell Set-GitHubConfiguration -DisableSmarterObjects:$false Measure-Command { $c = Get-GitHubContent -OwnerName microsoft -RepositoryName PowerShellForGitHub -Path README.md } # This averages to be around 1.2 seconds Set-GitHubConfiguration -DisableSmarterObjects:$true Measure-Command { $c = Get-GitHubContent -OwnerName microsoft -RepositoryName PowerShellForGitHub -Path README.md } # This averages to be around 14 seconds ``` The reasoning behind this was that the return of `Invoke-WebRequest` for this repo's `README.md` was an array of [int32] that contained 22,000+ entries (one byte per entry). Because the array was created by `ConverFrom-Json`, each `[int32]` was also an `[object]`, which meant that it was considered a `[PSCustomObject]` inside of `ConverTo-SmarterObject`, which caused it to do a lot of unnecessary work. Piping in 22,000 objects and doing all of that unnecessary work to end up just calling `Write-Output` on the original value took a _lot_ of time. The fix here was to skip trying to convert the result to a smarter object if it wasn't going to be a convertible object in the first place. I also added in protection directly to `ConverTo-SmarterObject` as well. It made things better than the current runtime, but still twice as slow as not calling it in the first place (average runtime of above command was 3.5 seconds when we allowed it to go into the command and then do nothing). This doesn't end up saving much time with the execution of `Tests/GitHubContents.tests.ps1` because the file being returned is so small, but this should have some nice user experience improvements in practical usage.
1 parent 6e794cb commit 7818776

File tree

2 files changed

+16
-3
lines changed

2 files changed

+16
-3
lines changed

GitHubCore.ps1

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,15 @@ function Invoke-GHRestMethod
348348

349349
if (-not (Get-GitHubConfiguration -Name DisableSmarterObjects))
350350
{
351-
$finalResult = ConvertTo-SmarterObject -InputObject $finalResult
351+
# In the case of getting raw content from the repo, we'll end up with a large object/byte
352+
# array which isn't convertible to a smarter object, but by _trying_ we'll end up wasting
353+
# a lot of time. Let's optimize here by not bothering to send in something that we
354+
# know is definitely not convertible ([int32] on PS5, [long] on PS7).
355+
if (($finalResult -isnot [Object[]]) -or
356+
(($finalResult.Count -gt 0) -and ($finalResult[0] -isnot [int]) -and ($finalResult[0] -isnot [long])))
357+
{
358+
$finalResult = ConvertTo-SmarterObject -InputObject $finalResult
359+
}
352360
}
353361

354362
$links = $result.Headers['Link'] -split ','
@@ -900,7 +908,13 @@ filter ConvertTo-SmarterObject
900908
return $null
901909
}
902910

903-
if ($InputObject -is [System.Collections.IList])
911+
if (($InputObject -is [int]) -or ($InputObject -is [long]))
912+
{
913+
# In some instances, an int/long was being seen as a [PSCustomObject].
914+
# This attempts to short-circuit extra work we would have done had that happened.
915+
Write-Output -InputObject $InputObject
916+
}
917+
elseif ($InputObject -is [System.Collections.IList])
904918
{
905919
$InputObject |
906920
ConvertTo-SmarterObject |

Tests/GitHubAnalytics.tests.ps1

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ try
2828
for ($i = 0; $i -lt 4; $i++)
2929
{
3030
$newIssues += New-GitHubIssue -OwnerName $script:ownerName -RepositoryName $repo.name -Title ([guid]::NewGuid().Guid)
31-
Start-Sleep -Seconds 5
3231
}
3332

3433
$newIssues[0] = Update-GitHubIssue -OwnerName $script:ownerName -RepositoryName $repo.name -Issue $newIssues[0].number -State Closed

0 commit comments

Comments
 (0)