Why does my powershell runspace not increase performance?

so basically, i am looking at doing a comparison between accounts we have in Active Directory and a csv which lists all active accounts (~15000 lines). This process would be ran weekly.

The issue that I am coming across is that runspaces do not seem to increase performance of the script after a certain point; i.e., before using multiple runspaces, the script took about 28-30 minutes to gather and cross reference data but after incorporating 2 runspaces, that dropped down to ~18 minutes.

So i thought – thats great, increase available runspaces and should see multiplicative decrease in time to process. Unfortunately, that isnt what happened, and as the script stands, I have increased the number of runspaces to 8, but only seen maybe 10 second performance increase.

Basically, I am getting the same performance out of 8 runspaces as I am getting out of 2 runspaces.

The server this runs on has 4 sockets, 2 cores per socket. Am i stupid? Missing something obvious? Or do i need to research and get a better handle on expected gains from multiple runspaces?

And yes, I know I am not using the term delta list accurately; changed process halfway through and never went back to correct var names 🙂

#Declarations
$DeltaListInactive = @() #these accounts exist in AD within the account OU, but are not actively enrolled accounts
$DeltaListActiveNotFound = @() #these accounts exist only in the CSV import - accounts have not been created or otherwise do not exist in AD, no actions will be processed against these accounts
$DeltaListActive = [System.Collections.Queue]::Synchronized([System.Collections.Queue]::new()) #these accounts exist in the CSV Sheet, and in AD. Actively enrolled and may require accounts changes based on CSV Sheet
$CSVImport= [System.Collections.Queue]::Synchronized($SynImport)


#region Information Gathering
##Build Comparison/Delta list
$ImportComparison = Compare-Object -ReferenceObject $CSVImport.UserID -DifferenceObject $ADImport.sAMAccountName -IncludeEqual
foreach($result in $ImportComparison)
{
    if($result.SideIndicator -eq '=>') #these accounts are found in AD but do not exist in the CSV import; these accounts will be disabled and moved to the corresponding disabled account OU; logging for this process WILL NOT occur here
    {
        $DeltaListInactive += $result.InputObject
    }

    if($result.SideIndicator -eq '<=') #these accounts exist in the CSV import, but do not exist in AD; these accounts will not be processed in any way; logging for this process WILL occur here
    {
        $DeltaListActiveNotFound += $result.InputObject
        $ActiveNotFoundLog += "`r`n$((Get-Date).ToString("hh:mm:ss")) // Account --> $($result.InputObject) <-- not found in Active Directory. Account will not be processed."
    }
    
    if($result.SideIndicator -eq '==') #these accounts are found in AD and the CSV import; these accounts will be checked for any pending changes and have them applied; logging for this process WILL NOT occur here
    {
       $DeltaListActive.Enqueue($result.InputObject)
    }
}

$ActiveNotFoundLog | Out-File -FilePath $LogLocation$ActiveNotFoundLogFilename -Force -WhatIf:$false

$QueueCount = $DeltaListActive.Count

$ScriptBlock = {
    param (
        $DeltaListActive,
        $CSVImport
    )
    while( $DeltaListActive.Count -gt 0 ) {
        $Activeaccount = $DeltaListActive.Dequeue()

        #Gather account information from AD
        $ADUser = Get-ADUser -Identity $Activeaccount -Properties distinguishedName,memberof,surname,givenname,telephonenumber,enabled,employeeid,office
    
        #declare change flags
        [int]$ChangesRequired = 0
        [bool]$ChangeStatus = $false
        [bool]$ChangeOU = $false
        [bool]$ChangeBuilding = $false
        [bool]$ChangeGradYear = $false
        [bool]$ChangeaccountID = $false
        [bool]$ChangeGroups = $false

        $CurrentADInfo = $null
        $CurrentADInfo = [PSCustomObject]@{
            AccountName = $ADUser.SamAccountName
            Enabled = $ADUser.Enabled
            OrgUnit = ($ADUser.DistinguishedName.Split(",") | Where-Object {-Not $_.StartsWith("CN=")}) -join ","
            Building = $ADUser.Office
            GradYear = $ADUser.telephonenumber
            accountID = $ADUser.EmployeeID
            Groups = ($ADUser.MemberOf | Get-ADGroup | Select-Object Name).Name
        }

        $CSVUser = $CSVImport | Where-Object UserID -eq $Activeaccount
        $NewCSVInfo = $null
        $NewCSVInfo = [PSCustomObject]@{
            AccountName = $CSVUser.UserID
            Enabled = "True"
            OrgUnit = "OU=20$($CSVUser.'Year'),OU=accounts,OU=domain,DC=domain,DC=local"
            Building = $CSVUser.'Building Number'

            GradYear = "20$($CSVUser.'Year')"
            accountID = $CSVUser.accountID
            Groups = @("$($CSVUser.'Building Number')-accounts","accounts-Year')","Internet-All-accounts")
        }

        #Check for necessary changes and pass to action hash

        #if account disabled, then set required status change flag to true
        if(-not $CurrentADInfo.Enabled)
        {
            $ChangeStatus = $true
            $ChangesRequired++
        }

        #if incorrect OU, then set change GradYear flag
        if($CurrentADInfo.OrgUnit -ne $NewCSVInfo.OrgUnit)
        {
            $ChangeOU = $true
            $ChangesRequired++
        }

        #if incorrect building, then set change building flag
        if($CurrentADInfo.Building -ne $NewCSVInfo.Building)
        {
            $ChangeBuilding = $true
            $ChangesRequired++
        }

        #if incorrect Gradyear, then set change gradyear flag
        if($CurrentADInfo.GradYear -ne $NewCSVInfo.GradYear)
        {
            $ChangeGradYear = $true
            $ChangesRequired++
        }

        #if incorrect accountid, then set change accountid flag
        if($CurrentADInfo.accountID -ne $NewCSVInfo.accountID)
        {
            $ChangeaccountID = $true
            $ChangesRequired++
        }

        #if incorrect groups, then set change groups flag
        $CorrectGroupCount = 0
        foreach($group in $NewCSVInfo.Groups)
        {
            if($CurrentADInfo.Groups -match $group)
            {
                $CorrectGroupCount++
            }
        }

        if($CorrectGroupCount -ne $NewCSVInfo.Groups.Count)
        {
            $ChangeGroups = $true
            $ChangesRequired++
        }

        $CurrentUserActions = [PSCustomObject]@{
            account_Username = $ADUser.SamAccountName
            Distinguished_Name = $ADUser.DistinguishedName
            Changes_Required = $ChangesRequired
            Status_Change_Required = $ChangeStatus
            OU_Change_Required = $ChangeOU
            Building_Change_Required = $ChangeBuilding
            GradYear_Change_Required = $ChangeGradYear
            accountID_Change_Required = $ChangeaccountID
            Group_Change_Required = $ChangeGroups
            OLD_ENABLED = $CurrentADInfo.Enabled
            NEW_ENABLED = $NewCSVInfo.Enabled
            OLD_OU = $CurrentADInfo.OrgUnit
            NEW_OU = $NewCSVInfo.OrgUnit
            OLD_BUILDING = $CurrentADInfo.Building
            NEW_BUILDING = $NewCSVInfo.Building
            OLD_GRADYEAR = $CurrentADInfo.GradYear
            NEW_GRADYEAR = $NewCSVInfo.GradYear
            OLD_accountID = $CurrentADInfo.accountID
            NEW_accountID = $NewCSVInfo.accountID
            OLD_GROUPS = $CurrentADInfo.Groups -join ','
            NEW_GROUPS = $NewCSVInfo.Groups -join ','
        }
        if($ChangesRequired -gt 0)
        {
            $CurrentUserActions
        }
    }
    
}

$Inputs = New-Object 'System.Management.Automation.PSDataCollection[PSObject]'
$ActiveActionHash = New-Object 'System.Management.Automation.PSDataCollection[PSObject]'

$runspace_start = Get-Date
Write-Host "Starting runspaces... $($runspace_start.ToString("hh:mm:ss"))"

$Instances = @()
(1..8) | ForEach-Object { # (1..X) signifies the number of runspaces to create in order to process these requests
    $Instance = [powershell]::Create().AddScript($ScriptBlock).AddParameter('DeltaListActive', $DeltaListActive).AddParameter('CSVImport',$CSVImport)
    $Instances += New-Object PSObject -Property @{
        Instance = $Instance
        State = $Instance.BeginInvoke($Inputs,$ActiveActionHash)
    }
}

while ( $Instances.State.IsCompleted -contains $False) {
    # Report the accounts left in the queue
    $time_spent = [Timespan]::FromMilliseconds(((Get-Date) - $runspace_start).TotalMilliseconds)
    Write-Progress -Activity "Gathering account information..." -Status "account(s) Remaining: $($DeltaListActive.Count)/$($QueueCount)... $($time_spent.Hours)h $($time_spent.Minutes)m $($time_spent.Seconds)s" -PercentComplete (($DeltaListActive.count/$QueueCount)*100)
    
}

11

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật