'Powershell performance : nested foreach vs foreach in series
I am doing some performance profiling on registry search, and I have found a definite performance difference between these two loop structures, and I wonder what is going on under the hood to explain it? From a readability standpoint I prefer the nested foreach (Loops2) over the loops in series (Loops1). However, Loops1 consistently runs in about 55% of the time of Loops2. Now, to be honest I don't know that it REALLY matters, given that I am running each loop 100 times and the slow one is still under 1 second (.88) and in actual use I will likely not run the loop even half as many times as that, often much lower. But I feel like just the fact that I am doing the performance profiling is a real improvement in my approach, and understanding WHY one performs better than the other would be valuable too. I may well use the slower approach because of readability, but perhaps there is something in the why that will convince me otherwise.
$regKeys = @('Registry::HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall',
'Registry::HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall')
$regKeyNames = @('SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall',
'SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall')
$searchPropertyValue = 'Microsoft Visual C++ 2012 Redistributable (x64) - 11.0.61030'
Write-Host "`r`nLoops1 " -noNewLine
(Measure-Command {
foreach ($i in 1..100) {
$installedPrograms = Get-ChildItem -Path:$regKeys[0]
:x64 foreach ($installedProgram in $installedPrograms) {
if ($installedProgram.GetValue('DisplayName') -eq $searchPropertyValue) {
$found = $installedProgram
break x64
}
}
if (-not $found) {
$installedPrograms = Get-ChildItem -Path:$regKeys[1]
:x32 foreach ($installedProgram in $installedPrograms) {
if ($installedProgram.GetValue('DisplayName') -eq $searchPropertyValue) {
$found = $installedProgram
break x32
}
}
}
}
}).TotalSeconds
Write-Host "$found"
Write-Host "`r`nLoops2 " -noNewLine
(Measure-Command {
foreach ($i in 1..100) {
:search foreach ($key in $regKeys) {
$installedPrograms = Get-ChildItem -Path:$key
foreach ($installedProgram in $installedPrograms) {
if ($installedProgram.GetValue('DisplayName') -eq $searchPropertyValue) {
$found = $installedProgram
break search
}
}
}
}
}).TotalSeconds
Write-Host "$found"
Write-Host "`r`n[Microsoft.Win32.RegistryHive] " -noNewLine
(Measure-Command {
$localMachineHive = [Microsoft.Win32.RegistryKey]::OpenBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, 0)
foreach ($i in 1..100) {
:search foreach ($keyName in $regKeyNames) {
if (($installedProgram = $localMachineHive.OpenSubKey("$keyName\$uninstallKeyName")).GetValue('DisplayName') -eq $searchPropertyValue1) {
$found = $installedProgram
break search
}
}
}
}).TotalSeconds
Write-Host "$found"
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
