dsccommunity/ExchangeDsc

xExchOABVirtualDirectory: Large numbers of Offline Address Books cause scaling issue

Opened this issue · 1 comments

When using xExchOABVirtualDirectory with large numbers of offline address books, this resource takes a very long time to test.

For example we have approximately 65 thousand OABs and in testing with Invoke-DscResource, this resource took 2321 seconds to complete.

This was using a relatively simple configuration:

$invokeParams = @{
    Name       = 'xExchOabVirtualDirectory'
    ModuleName = @{
        modulename    = 'xExchange'
        moduleversion = '1.27.0.0'
    }
    Method     = 'test'
    Property   = @{
        'identity' = 'servername\OAB (Default Web Site)';
        'allowServiceRestart' = $true;
        'internalURL' = 'https://domainname.tld/OAB';
        'externalURL' = 'https://domainname.tld/OAB';
        'credential' = $cred
    }
}
Invoke-DscResource @InvokeParams

I think the issue exists here:
https://github.com/dsccommunity/xExchange/blob/078fd0883cf2f5560513bd3a4ee0187aee32182a/source/DSCResources/MSFT_xExchOabVirtualDirectory/MSFT_xExchOabVirtualDirectory.psm1#L87-L97

I think there are two fixes which could be applied:

  1. Using += to generate an array inside a foreach is costly in PS5, it could be replaced with a select-object?
$oabs = Get-OfflineAddressBook @PSBoundParameters | Where-Object {$_.VirtualDirectories -like "*$($Identity)*"} | Select-Object -ExpandProperty Name
  1. Wrap these lines inside If($PSBoundParameters.ContainsKey('OABsToDistribute')) as Test and Set both do.

Hi @jrdbarnes , thanks for the submission. I agree, the += on the array could definitely cause perf issues if a large number of OAB's are returned by Get-OfflineAddressBook. That said, are you sure that's actually where the delay is? Might be worthwhile adding some custom Write-Verbose logging with time stamps throughout that code section to confirm where the delay is. Given your sample config, I would expect:

Get-OfflineAddressBook @PSBoundParameters | Where-Object {$_.VirtualDirectories -like "*$($Identity)*"}

to translate to:

Get-OfflineAddressBook @PSBoundParameters | Where-Object {$_.VirtualDirectories -like "*servername\OAB (Default Web Site)*"}

I wouldn't expect that to return more than one OAB, unless that server has multiple OAB's, and all start with 'OAB (Default Web Site)'. My thinking is that if anywhere, this is actually getting delayed by the Get-OfflineAddressBook call, before the Where-Object filter is even applied. If that is the case, the correct fix may be to update the Get-OfflineAddressBook call to use the -Identity parameter (and possibly fall back to the existing method if it fails).