Sometimes you need to know how long it takes to execute a PowerShell script or a particular block of code. This allows you to predict how long it will take for the script to perform the required action, make changes to your system settings, or return a result. There are several ways to measure the execution time of a PowerShell command or script in Windows.
Execution Time in PowerShell Command History
The easiest way is to simply query the command execution time in the console from the PowerShell command history. The start and end times of the command are contained in the StartExecutionTime and EndExecutionTime attributes:
Get-History | select StartExecutionTime,EndExecutionTime,CommandLine
Get the execution time of the last PowerShell command:
$lastcommand=Get-History | select -Last 1 -Property *
$lastcommand.EndExecutionTime - $lastcommand.StartExecutionTime
The last command calculates the difference between the time at which the command was completed and the time at which it was started. As a result, you get the PowerShell command execution time in seconds (TotalSeconds), milliseconds (TotalMilliseconds), etc.
Only the final value can be output:
($lastcommand.EndExecutionTime - $lastcommand.StartExecutionTime). TotalSeconds
Get PowerShell Code Execution Time with Measure-Command
You can use the built-in Measure-Command cmdlet to get the total time (in milliseconds) that all the commands in a block of PowerShell code take to execute.
This cmdlet takes the command (command block) specified in curly braces, executes it internally, and returns the time it took to execute as a result.
Measure-Command -Expression {"{0:N2} GB" -f ((gci –force c:\photo –Recurse -ErrorAction SilentlyContinue| measure Length -s).sum / 1Gb)
Get-Event
}
In this example, the command block was executed in 710 milliseconds.
You can convert the result into a more convenient time format:
$cmd_time = Measure-Command -Expression {Get-Event}
$cmd_time.ToString()
You can use the Measure command to get the execution time of a PowerShell script file (*.PS1):
Measure-Command { ./myScript.ps1 }
To view the execution time of a console command (or PS1 script compiled into exe), you can also use the Measure-Command cmdlet:
Measure-Command {ping 8.8.8.8}
Output PowerShell Code Execution Time as Differencing in DateTime Object
If you need to determine the execution time in a PowerShell script, you need to get the date value at the beginning of the script and compare it with the date at the end of the script.
$StartTime = (Get-Date)
Start-Sleep -Seconds 10
$EndTime = (Get-Date)
$TotalTime = $EndTime-$StartTime
$TotalTime
You can use transformation to get the execution time in a convenient form:
$TotalTime.ToString()
or:
'{0:mm} min {0:ss} sec' -f $TotalTime
Using Stopwatch in PowerShell Scripts
This is a .Net class that works like a real-life stopwatch. Start the stopwatch at a specified time and stop it using PowerShell. The stopwatch will return the time that has elapsed between its start and stop. This is the execution time of your code block or PowerShell script.
The StopWatch generic .Net class is available in all versions of PowerShell (including Windows PowerShell and PowerShell Core). Let’s look at an example of code that starts, stops, and displays a stopwatch value.
$watch = [System.Diagnostics.Stopwatch]::StartNew()
$watch.Start() # Timer start
# your PowerShell script code
$watch.Stop() # Stopping the timer
Write-Host $watch.Elapsed # Print script execution time
$watch.IsRunning
method. The speed of script execution can be affected by the overall load on the operating system, the speed of the network connection, and other factors. The execution time for the same PowerShell code can vary significantly. If you need to get the predicted execution time for PowerShell code, be sure to measure the script execution time several times.
Optimizing PowerShell Script Execution Speed
To increase the speed of your PowerShell scripts, you must take advantage of the capabilities of cmdlets.
For example, when querying a list of users from AD using the Get-ADUser command, it is better to use filters on the server side to select users. Compare the execution times of the following commands:
Get-ADUser -Filter {Enabled -eq "true"}
Get-ADUser | Where-Object {$_.enabled -eq $true}
The time taken to execute the first command is much shorter because the fetching is done on the server side. In addition, your computer will receive less data over the network because the server will only send back the objects that you have requested.
The second command returns all objects from the domain controller and then filters the result on the client side.
A similar result can be seen if you use Get-WinEvent to request a list of events from the Event Viewer logs.
Let’s get a list of errors from the Event Viewer for 10 days using Where-Object and FilterHashtable. Then let’s use Measure-Command to compare the execution speed of these two PowerShell commands:
$StartDate = (Get-Date).AddDays(-10)
Check the command execution time when using the Where-Object:
(Measure-Command {Get-WinEvent System | Where-Object {($_.LevelDisplayName -eq "Error") -and ($_.TimeCreated -ge $StartDate )}}).TotalMilliseconds
Now let’s use the filtering feature on the side of the Event Viewer service by using the FilterHashtable parameter:
(Measure-Command {Get-WinEvent -FilterHashtable @{LogName = 'System'; Level =3; StartTime=$StartDate }}).TotalMilliseconds
In this example, you can see that the command to select events using the FilterHashtable is 40 (!!!) times faster than using the usual Where-Object (0.7 sec vs 26 sec).