Code Snippet: Process Time as Percentage of Total CPU Time

A couple of weeks ago, a colleague of mine asked me how I would determine a process’ CPU utilization as a percentage of total CPU time. I came up with this PowerShell code, but it’s not quite complete yet, because it doesn’t dynamically determine the number of cores that a system has.

During the investigation of this problem, I came across a few key learnings:

  1. The system’s last boot-up time must be converted from WMI DateTime format to a .NET System.DateTime struct so that one can be properly subtracted from the other using the System.DateTime’s subtraction operator overload
  2. Retrieving the number of cores from a system depends on the operating system. For XP/2003, you would use Win32_ComputerSystem.NumberOfProcessors, but on Vista / 7 / 2008 / 2008 R2 you would use the Win32_ComputerSystem.NumberOfLogicalProcessors property. This is important in calculating total [virtual] system uptime. It’s simply <RealTime> * <NumberOfCores> as best I can tell
  3. If a process is closed and restarted, you will not get an accurate percentage … perhaps you could use the CreationDate property of the Win32_Process WMI class to determine how long a process has been running, versus total system uptime

The PowerShell code below retrieves the percentage of CPU time that the System Idle Process has consumed on a dual-core (or single core, hyper-threaded) system.

Please note that modifications are required for other hardware configurations; I have not yet had a chance to revise the code appropriately, but I have addressed it above.

$proc = Get-WmiObject -Query "select * from Win32_Process where name = 'System Idle Process'"
$proccputime = [TimeSpan]::FromSeconds(($proc.UserModeTime + $proc.KernelModeTime) / 10000000) #virtual CPU time, not real
Write-Host "Process seconds: $($proccputime.TotalSeconds)"
$virtuptime = [TimeSpan]([DateTime]::Now - [System.Management.ManagementDateTimeconverter]::ToDateTime((Get-WmiObject Win32_OperatingSystem).LastBootUpTime))
# This next line assumes a 2nd core by adding the TimeSpan to itself
$virtuptime += $virtuptime
Write-Host "Total system uptime (seconds): $($virtuptime.TotalSeconds)"
$percentage = ($proccputime.TotalSeconds / $virtuptime.TotalSeconds) * 100
Write-Host "Process $($proc.Name) has used $percentage% of CPU time"