Home | History | Annotate | Line # | Download | only in Kernel
      1 #!/usr/bin/sh
      2 #
      3 # cputimes - print CPU time consumed by Kernel/Idle/Processes.
      4 #            Written using DTrace (Solaris 10 3/05).
      5 #
      6 # $Id: cputimes,v 1.1.1.1 2015/09/30 22:01:09 christos Exp $
      7 #
      8 # This program accurately measures time consumed by the kernel, but in
      9 # doing so creates extra kernel load of it's own. The extra kernel
     10 # activity can be measured by running one cputimes and then another, and
     11 # comparing the difference in kernel consumed time. This method can be
     12 # used to estimate the load created by other DTrace scripts.
     13 #
     14 # USAGE:	cputimes [-ahTV] [-t top] [interval [count]]
     15 #
     16 #		-a                # print all processes
     17 #		-T                # print totals
     18 #		-V                # don't print timestamps
     19 #		-t num            # print top num lines only
     20 #  eg,
     21 #		cputimes 1        # print every 1 second
     22 #		cputimes -a 10    # print all processes every 10 secs
     23 #		cputimes -at 8 5  # print top 8 lines every 5 secs
     24 #
     25 #
     26 # FIELDS: 
     27 #		THREADS         The following or the process name,
     28 #		IDLE            Idle time - CPU running idle thread
     29 #		KERNEL          Kernel time - Kernel servicing interrupts, ...
     30 #		PROCESS         Process time - PIDs running on the system
     31 #		TIME (ns)       Sum of the CPU time, ns (nanoseconds)
     32 #
     33 # NOTES:
     34 # * This takes into account multiple CPU servers, the total 
     35 # seconds consumed will be a multiple of the CPU count and interval.
     36 #
     37 # SEE ALSO: cpudists
     38 #           Heisenberg's uncertainty principle.
     39 #
     40 # COPYRIGHT: Copyright (c) 2005 Brendan Gregg.
     41 #
     42 # CDDL HEADER START
     43 #
     44 #  The contents of this file are subject to the terms of the
     45 #  Common Development and Distribution License, Version 1.0 only
     46 #  (the "License").  You may not use this file except in compliance
     47 #  with the License.
     48 #
     49 #  You can obtain a copy of the license at Docs/cddl1.txt
     50 #  or http://www.opensolaris.org/os/licensing.
     51 #  See the License for the specific language governing permissions
     52 #  and limitations under the License.
     53 #
     54 # CDDL HEADER END
     55 #
     56 # Author: Brendan Gregg  [Sydney, Australia]
     57 #
     58 # 27-Apr-2005   Brendan Gregg   Created this.
     59 # 22-Sep-2005      "      "	Fixed a key corruption bug.
     60 # 22-Sep-2005      "      "	Last update.
     61 #
     62 
     63 
     64 ##############################
     65 # --- Process Arguments ---
     66 #
     67 opt_all=0; opt_time=1; opt_top=0; opt_totals=0
     68 top=0; interval=1; count=1
     69 
     70 while getopts aht:TV name
     71 do
     72         case $name in
     73         a)      opt_all=1 ;;
     74         T)      opt_totals=1 ;;
     75         V)      opt_time=0 ;;
     76         t)      opt_top=1; top=$OPTARG ;;
     77         h|?)    cat <<-END >&2
     78 		USAGE: cputimes [-ahTV] [-t top] [interval [count]]
     79 		       cputimes                  # default output
     80 		               -a                # print all processes
     81 		               -T                # print totals
     82 		               -V                # don't print times
     83 		               -t num            # print top num lines only
     84 		          eg,
     85 		               cputimes 1        # print every 1 second
     86 		               cputimes -a 10    # all processes per 10 sec
     87 		               cputimes -at 8 5  # top 8 lines every 5 secs
     88 		END
     89 		exit 1
     90         esac
     91 done
     92 shift `expr $OPTIND - 1`
     93 
     94 if [ "$1" -gt 0 ]; then
     95         interval=$1; count=-1; shift
     96 fi
     97 if [ "$1" -gt 0 ]; then
     98 	count=$1; shift
     99 fi
    100 
    101 
    102 #################################
    103 # --- Main Program, DTrace ---
    104 #
    105 /usr/sbin/dtrace -n '
    106  #pragma D option quiet
    107 
    108  /*
    109   * Command line arguments
    110   */
    111  inline int OPT_all    = '$opt_all';
    112  inline int OPT_time   = '$opt_time';
    113  inline int OPT_totals = '$opt_totals';
    114  inline int OPT_top    = '$opt_top';
    115  inline int TOP        = '$top';
    116  inline int INTERVAL   = '$interval';
    117  inline int COUNTER    = '$count';
    118 
    119  /* Initialise variables */
    120  dtrace:::BEGIN
    121  {
    122 	cpustart[cpu] = 0;
    123 	counts = COUNTER;
    124 	secs = INTERVAL;
    125  }
    126 
    127  /* Flag this thread as idle */
    128  sysinfo:unix:idle_enter:idlethread
    129  {
    130 	idle[cpu] = 1;
    131  }
    132 
    133  /* Save kernel time between running threads */
    134  sched:::on-cpu 
    135  /cpustart[cpu]/
    136  {
    137 	this->elapsed = timestamp - cpustart[cpu];
    138 	@Procs["KERNEL"] = sum(this->elapsed);
    139  }
    140 
    141  /* Save the elapsed time of a thread */
    142  sched:::off-cpu,
    143  sched:::remain-cpu,
    144  profile:::profile-1sec
    145  /cpustart[cpu]/
    146  {
    147 	/* determine the name for this thread */
    148 	program[cpu] = pid == 0 ? idle[cpu] ? "IDLE" : "KERNEL" :
    149 	    OPT_all ? execname : "PROCESS";
    150 
    151 	/* save elapsed */
    152 	this->elapsed = timestamp - cpustart[cpu];
    153 	@Procs[program[cpu]] = sum(this->elapsed);
    154 	cpustart[cpu] = timestamp;
    155  }
    156 
    157  /* Record the start time of a thread */
    158  sched:::on-cpu,
    159  sched:::remain-cpu
    160  {
    161 	idle[cpu] = 0;
    162 	cpustart[cpu] = timestamp;
    163  }
    164 
    165 
    166  profile:::tick-1sec
    167  {
    168 	secs--;
    169  }
    170 
    171  /* Print time */
    172  profile:::tick-1sec 
    173  /secs == 0/
    174  { 
    175 	OPT_time ? printf("%Y,\n", walltimestamp) : 1;
    176 	printf("%16s %16s\n", "THREADS", "TIME (ns)");
    177  }
    178 
    179  /* Print report */
    180  profile:::tick-1sec 
    181  /secs == 0/ 
    182  { 
    183 	OPT_top ? trunc(@Procs, TOP) : 1;
    184 	printa("%16s %@16d\n", @Procs);
    185 	trunc(@Procs);
    186 	secs = INTERVAL;
    187 	counts--;
    188  }
    189 
    190  /* End of program */
    191  profile:::tick-1sec 
    192  /counts == 0/ 
    193  {
    194 	exit(0);
    195  }
    196 
    197  /* cleanup for Ctrl-C */
    198  dtrace:::END
    199  {
    200 	trunc(@Procs);
    201  }
    202 '
    203 
    204