gpt4 book ai didi

powershell - Powershell代码片段的哪一部分使运行时间很长?

转载 作者:行者123 更新时间:2023-12-03 00:31:55 28 4
gpt4 key购买 nike

我的任务是为我们的广告环境中的每个用户提供上次登录时间的报告,很明显,我首先向Google谷歌母亲询问了一些我可以重新利用的内容,但找不到任何可以检查多个域 Controller 并协调上一个域 Controller 的内容,然后吐出是否超过了任意设置的日期/天数。

这是代码:

foreach ($user in $usernames) {
$percentCmpUser = [math]::Truncate(($usernames.IndexOf($user)/$usernames.count)*100)
Write-Progress -Id 3 -Activity "Finding Inactive Accounts" -Status "$($percentCmpUser)% Complete:" -PercentComplete $percentCmpUser
$allLogons = $AllUsers | Where-Object {$_.SamAccountName -match $user}
$finalLogon = $allLogons| Sort-Object LastLogon -Descending |Select-Object -First 1
if ($finalLogon.LastLogon -lt $time.ToFileTime()) {
$inactiveAccounts += $finalLogon
}
}
$usernames是大约6000个用户名的列表
$AllUsers是18000个用户的列表,它包含10个我想在最终报告中访问的不同属性。我得到它的方法是在我关心的特定OU中为所有用户命中20个左右的DC中的三个。最终脚本实际上是6k * 20,因为我确实需要点击每个DC来确保我不会错过任何用户的登录。

这是 $time的计算方式:
$DaysInactive = 60
$todayDate = Get-Date
$time = ($todayDate).Adddays(-($DaysInactive))

每个变量都在脚本的其他地方使用,这就是为什么我将其分成这样的原因。

在您建议 LastLogonTimestamp之前,有人告诉我这还不够,当我询问将复制时间更改为最新时,我被告知“不,不会发生”。
Search-ADAccount似乎也无法提供不活跃用户的准确 View 。

我对所有有关如何使此特定代码段更快运行或如何使用不同方法在快速时间内获得相同结果的建议持开放态度。

截至目前,在特定OU中击中所有用户的每个DC大约需要10-20秒/ DC,然后上述代码段需要30-40分钟。

最佳答案

几件事情引人注目,但这里最大的性能杀手可能是以下两个语句:

$percentCmpUser = [math]::Truncate(($usernames.IndexOf($user)/$usernames.count)*100)
# and
$allLogons = $AllUsers | Where-Object {$_.SamAccountName -match $user}

...这两个语句都将显示 O(N ^ 2)(或二次方)性能特征-也就是说,每次将输入大小加倍时, 所花费的时间就会翻两番!

  • Array.IndexOf()实际上是一个循环

  • 让我们看第一个:
    $percentCmpUser = [math]::Truncate(($usernames.IndexOf($user)/$usernames.count)*100)

    可能不言而喻,但是这个方法调用: $usernames.IndexOf()可能需要在每次执行时遍历整个 $usernames列表-到最后一个 $user时,它需要遍历并比较 $user的所有6000项。

    有两种解决方法:

    使用常规的 for循环:
    for($i = 0; $i -lt $usernames.Count; $i++) {
    $user = $usernames[$i]
    $percent = ($i / $usernames.Count) * 100
    # ...
    }

    完全停止输出进度
    Write-Progress确实很慢-即使调用者抑制了Progress输出(例如 $ProgressPreference = 'SilentlyContinue'),使用进度流仍然会带来开销,尤其是在每次循环迭代中调用时。

    完全删除 Write-Progress将删除计算百分比的要求:)

    如果仍然需要输出进度信息,则可以通过有时仅调用 Write-Progress来节省一些开销,例如每100次迭代一次:
    for($i = 0; $i -lt $usernames.Count; $i++) {
    $user = $usernames[$i]
    if($i % 100 -eq 0){
    $percent = ($i / $usernames.Count) * 100
    Write-Progress -Id 3 -Activity "Finding Inactive Accounts" -PercentComplete $percent
    }
    # ...
    }

  • ... |Where-Object也是一个循环

  • 现在第二个:
    $allLogons = $AllUsers | Where-Object {$_.SamAccountName -match $user}

    ... 6000次,powershell必须枚举 $AllUsers中的所有18000个对象并测试它们的 Where-Object过滤器。

    代替使用数组和 Where-Object,考虑将所有用户加载到哈希表中:
    # Only need to run this once, before the loop
    $AllLogonsTable = @{}
    $AllUsers |ForEach-Object {
    # Check if the hashtable already contains an item associated with the user name
    if(-not $AllLogonsTable.ContainsKey($_.SamAccountName)){
    # Before adding the first item, create an array we can add subsequent items to
    $AllLogonsTable[$_.SamAccountName] = @()
    }

    # Add the item to the array associated with the username
    $AllUsersTable[$_.SamAccountName] += $_
    }

    foreach($user in $users){
    # This will be _much faster_ than $AllUsers |Where-Object ...
    $allLogons = $AllLogonsTable[$user]
    }

    哈希表具有疯狂的 查找-通过键查找对象比在数组上使用 Where-Object快得多。

    关于powershell - Powershell代码片段的哪一部分使运行时间很长?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60604659/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com