Updated 2016-11-17 11:41:40 by dkf

I've had occassion to provide CPU utilization feedback to the user. For instance, you might have a Tcl/Tk application that consumes lots of CPU cycles, but there are options which the user can implement to reduce the load. It's nice to provide direct feedback (without requiring the user to access a system utility). Your application might also manage other applications, in which you might need to know how those applications are consuming resources.

Although I first titled this Wiki page for CPU utilization, the following can also be applied to measuring memory usage, uptime, etc.

Problem How to determine CPU utilization for your running application.

Solution - UNIX Use ps. The Berkeley version of ps (Linux default, /usr/ucb/ps for Solaris) provides this bit of information, which can be retrieved rather easily via exec. I'll use Solaris as my example, since that's what I'm most familiar with.

If you execute /usr/ucb/ps, you'll get two or more lines that look like this:
  USER       PID %CPU %MEM   SZ  RSS TT       S    START  TIME COMMAND
  mgbacke   5681  0.1  0.2 2440 1960 pts/6    S 10:31:36  0:0 /usr/bin/tcsh

More then likely, you'll get a lot of lines like this. What we really want is just the line associated with our application. To do this, give the ps command the u option, followed by the PID (Process ID) of the application:
  /usr/ucb/ps u 5681

which would return the output shown above.

To implement the above from within a Tcl application, you might implement a procedure such as this:
  proc getCPUutil { } {
      set result [exec /usr/ucb/ps u [pid]]
      set cpuUtil [lindex $result 13]
  }

You could also inline the code by doing everything on one line, but that's not by style:
  set CPU [lindex [exec /usr/ucb/ps u [pid]] 13]

Marty Backe

HP, IBM, etc., users, please confirm a suitable version of ps is available.

Lars H: The Filesystem Hierarchy Standard requires there to be a /bin/ps utility. I'd be worried about trusting the order of columns though (and also about using lindex to parse them); consider instead using the -o option of ps to make it output just the quantity you're interested in.

MHN: ... which is
  exec ps -o%cpu --no-headers [pid]

DKF: … or (tested on OSX)
  exec ps -o "%cpu=" -p [pid]

Solution - Windows Using new (4.0 Beta 1 and later) TWAPI:
(tcl) 51 % set query [pdh_system_performance_query processor_utilization processor_utilization_per_cpu]
pdh1
(tcl) 52 % pdh_query_get $query
processor_utilization 0.5898441948604449 processor_utilization_per_cpu {_Total 0.5898441948604449 0,_Total 0.5898441948604449 0,0 1.163364324505478 0,1 0.39867081831209683 0,2 0.11191075348958579 0,3 0.685430883134619}
(tcl) 53 % after 1000
(tcl) 54 % pdh_query_get $query
processor_utilization 0.909173966151211 processor_utilization_per_cpu {_Total 0.909173966151211 0,_Total 0.909173966151211 0,0 1.626480876427261 0,1 0.7042291346437635 0,2 0.8067015503974817 0,3 0.4992843031363159}

The code below only works with older versions of TWAPI (4.0 Beta 1 and later do not support this option):
  package require twapi
  # Total CPU utilization
  set cpu_utilization [twapi::get_processor_info -processorutilization]
  # This process utilization
  set process_utilization [twapi::get_process_info [pid] -processorutilization]
  # This thread utilization
  set thread_utilization [twapi::get_thread_info [twapi::get_current_thread_id] -processorutilization]

Going deeper, one of the GSoC 2011 Executed Projects gives access to CPU performance counters on at least Linux and Windows.