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# 22-Sep-2005, ver 0.73 (check for newer versions) 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# 61 62 63############################## 64# --- Process Arguments --- 65# 66opt_all=0; opt_time=1; opt_top=0; opt_totals=0 67top=0; interval=1; count=1 68 69while getopts aht:TV name 70do 71 case $name in 72 a) opt_all=1 ;; 73 T) opt_totals=1 ;; 74 V) opt_time=0 ;; 75 t) opt_top=1; top=$OPTARG ;; 76 h|?) cat <<-END >&2 77 USAGE: cputimes [-ahTV] [-t top] [interval [count]] 78 cputimes # default output 79 -a # print all processes 80 -T # print totals 81 -V # don't print times 82 -t num # print top num lines only 83 eg, 84 cputimes 1 # print every 1 second 85 cputimes -a 10 # all processes per 10 sec 86 cputimes -at 8 5 # top 8 lines every 5 secs 87 END 88 exit 1 89 esac 90done 91shift `expr $OPTIND - 1` 92 93if [ "$1" -gt 0 ]; then 94 interval=$1; count=-1; shift 95fi 96if [ "$1" -gt 0 ]; then 97 count=$1; shift 98fi 99 100 101################################# 102# --- Main Program, DTrace --- 103# 104/usr/sbin/dtrace -n ' 105 #pragma D option quiet 106 107 /* 108 * Command line arguments 109 */ 110 inline int OPT_all = '$opt_all'; 111 inline int OPT_time = '$opt_time'; 112 inline int OPT_totals = '$opt_totals'; 113 inline int OPT_top = '$opt_top'; 114 inline int TOP = '$top'; 115 inline int INTERVAL = '$interval'; 116 inline int COUNTER = '$count'; 117 118 /* Initialise variables */ 119 dtrace:::BEGIN 120 { 121 cpustart[cpu] = 0; 122 counts = COUNTER; 123 secs = INTERVAL; 124 } 125 126 /* Flag this thread as idle */ 127 sysinfo:unix:idle_enter:idlethread 128 { 129 idle[cpu] = 1; 130 } 131 132 /* Save kernel time between running threads */ 133 sched:::on-cpu 134 /cpustart[cpu]/ 135 { 136 this->elapsed = timestamp - cpustart[cpu]; 137 @Procs["KERNEL"] = sum(this->elapsed); 138 } 139 140 /* Save the elapsed time of a thread */ 141 sched:::off-cpu, 142 sched:::remain-cpu, 143 profile:::profile-1sec 144 /cpustart[cpu]/ 145 { 146 /* determine the name for this thread */ 147 program[cpu] = pid == 0 ? idle[cpu] ? "IDLE" : "KERNEL" : 148 OPT_all ? execname : "PROCESS"; 149 150 /* save elapsed */ 151 this->elapsed = timestamp - cpustart[cpu]; 152 @Procs[program[cpu]] = sum(this->elapsed); 153 cpustart[cpu] = timestamp; 154 } 155 156 /* Record the start time of a thread */ 157 sched:::on-cpu, 158 sched:::remain-cpu 159 { 160 idle[cpu] = 0; 161 cpustart[cpu] = timestamp; 162 } 163 164 165 profile:::tick-1sec 166 { 167 secs--; 168 } 169 170 /* Print time */ 171 profile:::tick-1sec 172 /secs == 0/ 173 { 174 OPT_time ? printf("%Y,\n", walltimestamp) : 1; 175 printf("%16s %16s\n", "THREADS", "TIME (ns)"); 176 } 177 178 /* Print report */ 179 profile:::tick-1sec 180 /secs == 0/ 181 { 182 OPT_top ? trunc(@Procs, TOP) : 1; 183 printa("%16s %@16d\n", @Procs); 184 trunc(@Procs); 185 secs = INTERVAL; 186 counts--; 187 } 188 189 /* End of program */ 190 profile:::tick-1sec 191 /counts == 0/ 192 { 193 exit(0); 194 } 195 196 /* cleanup for Ctrl-C */ 197 dtrace:::END 198 { 199 trunc(@Procs); 200 } 201' 202 203