Script Efficiency question

I understand that efficiency can mean different things to different people, but I’m really just looking to see if there are different ways to accomplish the goal that might be different than how I’ve written scripts in the past that PowerShell might be able to handle natively. Rather than grabbing all the data and shoving it in an array, then processing each result by the IF/ELSE statements? Heck, would it just be better to take each of the Get-Date values and establish that in the BEGIN block so I don’t have to spend the processing time each loop?

$DomainUsers = Get-ADUser -SearchBase 'OU=Users,DC=Contoso,DC=Com' -Properties lastlogondate
    Foreach ($user in $DomainUsers)
        {
            IF($user.lastlogondate -le ((Get-Date).AddDays(-90)))
                {
                #Action to take
                }
            ELSEIF($user.lastlogondate -le ((Get-Date).AddDays(-180)) -AND $user.lastlogindate -gt (Get-Date).AddDays(-90))
                {
                #Action to take
                }
            ELSEIF($user.lastlogondate -le ((Get-Date).AddDays(-270)) -AND $user.lastlogindate -gt (Get-Date).AddDays(-180))
                {
                #Action to take
                }
            ELSE
                {
                #Action to take
                }
        }

In terms of the Get-Date question, it’s not like that particular command takes a long time to complete. Yes, over 10,000 users, running Get-Date each time might add up to an extra second or two of runtime… but that’s hardly a lot. I’d argue, though, that calculating your dates up front would make the remaining script more legible, which is also important.

It’s also worth noting that Measure-Command can let you test different approaches against each other and see which one is faster.

I’d argue that a true PowerShell approach would be build to run in a single pipeline.

Get-ADUser | Where-MyADUserCriteria | Etc

Where “Where-MyADUserCriteria” accepts pipeline input and has your big If construct. In that fashion, it would get one item at a time, and would be able to operate somewhat in parallel with Get-ADUser. But there’s always a tradeoff. I bet your script as-is might run faster, but might use more memory to do so. My pipeline way might use less memory, but it could run a bit slower.

Another thing to consider is that issuing Get-Date on each instance makes your date a moving target. For example, if it takes your script 5 minutes to run and your script starts at 12:00:00 PM, then the AD users processed at the beginning of the file will be (x) days from 12:00:00, 01, 02, etc., but the users at the end of the process will be (x) days from 12:04:57, 58, 59, etc.

Of course the longer the script runs the longer the time is skewed. This may be OK, depending on the goal of the script, but if your process needs a consistent time to compare all accounts, you should calculate at the beginning of the process. With Don’s pipeline suggestion, this would be in the begin {} block.

Thank you Don and Curtis for your responses. While the delay in processing over the course of the script isn’t something anyone quibbles over (After 90+ days, whats a 4 minute variance) but it would be just a simpler reference point and look nicer as well.

Thanks again!