我的代码按预期工作。我真的很想知道是否有人知道为什么我下面描述的事情可能会发生。也就是说,如果有人有任何进一步优化日常工作的想法,我会本着每天都是上学日的精神感激地接受他们!
该脚本正在查询我们所有的域控制器以获取最新的最后登录特定 OU 中所有用户的属性。 (我这样做而不是使用上次登录时间戳属性,因为我需要脚本运行时的绝对最新登录信息。)
在测试过程中,为了检查代码是否按照我的预期执行,我添加了一些控制台输出(包含在下面的代码片段中)。
当我这样做时,我注意到第二次的每次迭代ForEach ( $DC in $AllDCs )
循环中,在嵌套循环写入控制台输出的第一行之前有一个明显的暂停。暂停的持续时间随着外循环的每次迭代而增加,并且内循环后续输出的速度也明显下降。在运行过程中,查看十多个 DC 的输出,我估计控制台线路的写入速率至少下降了 4 倍。
$AllDCs = Get-ADDomainController -Filter *
$AllRecords = @{}
ForEach ( $DC in $AllDCs ) {
$UserList = Get-ADUser -filter * -Server $DC -SearchBase $ini.OUDN.NewStartsInternal -SearchScope OneLevel -Properties lastLogon
$UserList = $UserList | Where { $_.SamAccountName -match $ini.RegEx.PayNo }
$AllRecords.Add($DC.Hostname,$UserList)
}
$Logons = @{}
ForEach ( $DC in $AllDCs ) { ; this loop is the one I'm talking about
ForEach ( $User in $AllRecords.$($DC.HostName) ) {
If ( $Logons.ContainsKey($User.SamAccountName) ) { ;this line amended on advice from mklement0
If ( $Logons.$($User.SamAccountName) -lt $User.lastLogon ) {
$Logons.$($User.SamAccountName) = $User.lastLogon
Write-Host "Updated $($User.SamAccountName) to $($User.lastLogon)" -ForegroundColor Green
} Else {
Write-Host "Ignored $($User.SamAccountName)"
}
} Else {
$Logons.Add( $User.SamAccountName , $User.lastLogon )
Write-Host "Created $($User.SamAccountName)" -ForegroundColor Yellow
}
}
}
我在这里实际上没有任何时间限制,因为我们只谈论几百个用户和十几个域控制器。无论如何,我已经大大减少了运行时间。以前,它循环遍历用户并逐一查询每个用户的每个 DC,毫不奇怪,这花费了更长的时间。
UPDATE:
我从下面的第一条评论中实现了 mklement0 的建议,如果有的话,脚本实际上运行得比以前慢。外循环迭代之间的延迟较长,并且内循环的输出似乎受到随机延迟的影响。平均而言,我认为内部循环每秒进行约 2 到 3 次迭代,在我看来,这对于循环已保存在本地内存中的数据来说非常慢。我知道 PowerShell 因速度慢而闻名,但这似乎很特殊。
该脚本通常在虚拟机上运行,所以我在自己的计算机上测试了它,速度慢了很多,所以这不是虚拟机的资源问题。
更新2:
我删除了所有Write-Host
命令并简单地计时外循环的每次迭代。
首先,删除所有控制台写入会显着提高性能,这是我所期望的,尽管我没有意识到提高了多少。它轻松地将运行时间缩短到原来的五分之一。
就循环时间而言,奇怪的行为仍然存在。在 12 次迭代中,前 7 次在 1 秒内完成,完成最后 5 次大约需要 35 秒。这种行为每次都会或多或少地重复。与前七个 DC 相比,最后五个 DC 的主机名没有任何不同,这可能会减慢哈希表查找速度。
我对现在的运行时间非常满意,但仍然对这种奇怪的行为感到非常困惑。