1235368Sgnn#!/usr/bin/sh 2235368Sgnn# 3235368Sgnn# cputimes - print CPU time consumed by Kernel/Idle/Processes. 4235368Sgnn# Written using DTrace (Solaris 10 3/05). 5235368Sgnn# 6235368Sgnn# $Id: cputimes 3 2007-08-01 10:50:08Z brendan $ 7235368Sgnn# 8235368Sgnn# This program accurately measures time consumed by the kernel, but in 9235368Sgnn# doing so creates extra kernel load of it's own. The extra kernel 10235368Sgnn# activity can be measured by running one cputimes and then another, and 11235368Sgnn# comparing the difference in kernel consumed time. This method can be 12235368Sgnn# used to estimate the load created by other DTrace scripts. 13235368Sgnn# 14235368Sgnn# USAGE: cputimes [-ahTV] [-t top] [interval [count]] 15235368Sgnn# 16235368Sgnn# -a # print all processes 17235368Sgnn# -T # print totals 18235368Sgnn# -V # don't print timestamps 19235368Sgnn# -t num # print top num lines only 20235368Sgnn# eg, 21235368Sgnn# cputimes 1 # print every 1 second 22235368Sgnn# cputimes -a 10 # print all processes every 10 secs 23235368Sgnn# cputimes -at 8 5 # print top 8 lines every 5 secs 24235368Sgnn# 25235368Sgnn# 26235368Sgnn# FIELDS: 27235368Sgnn# THREADS The following or the process name, 28235368Sgnn# IDLE Idle time - CPU running idle thread 29235368Sgnn# KERNEL Kernel time - Kernel servicing interrupts, ... 30235368Sgnn# PROCESS Process time - PIDs running on the system 31235368Sgnn# TIME (ns) Sum of the CPU time, ns (nanoseconds) 32235368Sgnn# 33235368Sgnn# NOTES: 34235368Sgnn# * This takes into account multiple CPU servers, the total 35235368Sgnn# seconds consumed will be a multiple of the CPU count and interval. 36235368Sgnn# 37235368Sgnn# SEE ALSO: cpudists 38235368Sgnn# Heisenberg's uncertainty principle. 39235368Sgnn# 40235368Sgnn# COPYRIGHT: Copyright (c) 2005 Brendan Gregg. 41235368Sgnn# 42235368Sgnn# CDDL HEADER START 43235368Sgnn# 44235368Sgnn# The contents of this file are subject to the terms of the 45235368Sgnn# Common Development and Distribution License, Version 1.0 only 46235368Sgnn# (the "License"). You may not use this file except in compliance 47235368Sgnn# with the License. 48235368Sgnn# 49235368Sgnn# You can obtain a copy of the license at Docs/cddl1.txt 50235368Sgnn# or http://www.opensolaris.org/os/licensing. 51235368Sgnn# See the License for the specific language governing permissions 52235368Sgnn# and limitations under the License. 53235368Sgnn# 54235368Sgnn# CDDL HEADER END 55235368Sgnn# 56235368Sgnn# Author: Brendan Gregg [Sydney, Australia] 57235368Sgnn# 58235368Sgnn# 27-Apr-2005 Brendan Gregg Created this. 59235368Sgnn# 22-Sep-2005 " " Fixed a key corruption bug. 60235368Sgnn# 22-Sep-2005 " " Last update. 61235368Sgnn# 62235368Sgnn 63235368Sgnn 64235368Sgnn############################## 65235368Sgnn# --- Process Arguments --- 66235368Sgnn# 67235368Sgnnopt_all=0; opt_time=1; opt_top=0; opt_totals=0 68235368Sgnntop=0; interval=1; count=1 69235368Sgnn 70235368Sgnnwhile getopts aht:TV name 71235368Sgnndo 72235368Sgnn case $name in 73235368Sgnn a) opt_all=1 ;; 74235368Sgnn T) opt_totals=1 ;; 75235368Sgnn V) opt_time=0 ;; 76235368Sgnn t) opt_top=1; top=$OPTARG ;; 77235368Sgnn h|?) cat <<-END >&2 78235368Sgnn USAGE: cputimes [-ahTV] [-t top] [interval [count]] 79235368Sgnn cputimes # default output 80235368Sgnn -a # print all processes 81235368Sgnn -T # print totals 82235368Sgnn -V # don't print times 83235368Sgnn -t num # print top num lines only 84235368Sgnn eg, 85235368Sgnn cputimes 1 # print every 1 second 86235368Sgnn cputimes -a 10 # all processes per 10 sec 87235368Sgnn cputimes -at 8 5 # top 8 lines every 5 secs 88235368Sgnn END 89235368Sgnn exit 1 90235368Sgnn esac 91235368Sgnndone 92235368Sgnnshift `expr $OPTIND - 1` 93235368Sgnn 94235368Sgnnif [ "$1" -gt 0 ]; then 95235368Sgnn interval=$1; count=-1; shift 96235368Sgnnfi 97235368Sgnnif [ "$1" -gt 0 ]; then 98235368Sgnn count=$1; shift 99235368Sgnnfi 100235368Sgnn 101235368Sgnn 102235368Sgnn################################# 103235368Sgnn# --- Main Program, DTrace --- 104235368Sgnn# 105235368Sgnn/usr/sbin/dtrace -n ' 106235368Sgnn #pragma D option quiet 107235368Sgnn 108235368Sgnn /* 109235368Sgnn * Command line arguments 110235368Sgnn */ 111235368Sgnn inline int OPT_all = '$opt_all'; 112235368Sgnn inline int OPT_time = '$opt_time'; 113235368Sgnn inline int OPT_totals = '$opt_totals'; 114235368Sgnn inline int OPT_top = '$opt_top'; 115235368Sgnn inline int TOP = '$top'; 116235368Sgnn inline int INTERVAL = '$interval'; 117235368Sgnn inline int COUNTER = '$count'; 118235368Sgnn 119235368Sgnn /* Initialise variables */ 120235368Sgnn dtrace:::BEGIN 121235368Sgnn { 122235368Sgnn cpustart[cpu] = 0; 123235368Sgnn counts = COUNTER; 124235368Sgnn secs = INTERVAL; 125235368Sgnn } 126235368Sgnn 127235368Sgnn /* Flag this thread as idle */ 128235368Sgnn sysinfo:unix:idle_enter:idlethread 129235368Sgnn { 130235368Sgnn idle[cpu] = 1; 131235368Sgnn } 132235368Sgnn 133235368Sgnn /* Save kernel time between running threads */ 134235368Sgnn sched:::on-cpu 135235368Sgnn /cpustart[cpu]/ 136235368Sgnn { 137235368Sgnn this->elapsed = timestamp - cpustart[cpu]; 138235368Sgnn @Procs["KERNEL"] = sum(this->elapsed); 139235368Sgnn } 140235368Sgnn 141235368Sgnn /* Save the elapsed time of a thread */ 142235368Sgnn sched:::off-cpu, 143235368Sgnn sched:::remain-cpu, 144235368Sgnn profile:::profile-1sec 145235368Sgnn /cpustart[cpu]/ 146235368Sgnn { 147235368Sgnn /* determine the name for this thread */ 148235368Sgnn program[cpu] = pid == 0 ? idle[cpu] ? "IDLE" : "KERNEL" : 149235368Sgnn OPT_all ? execname : "PROCESS"; 150235368Sgnn 151235368Sgnn /* save elapsed */ 152235368Sgnn this->elapsed = timestamp - cpustart[cpu]; 153235368Sgnn @Procs[program[cpu]] = sum(this->elapsed); 154235368Sgnn cpustart[cpu] = timestamp; 155235368Sgnn } 156235368Sgnn 157235368Sgnn /* Record the start time of a thread */ 158235368Sgnn sched:::on-cpu, 159235368Sgnn sched:::remain-cpu 160235368Sgnn { 161235368Sgnn idle[cpu] = 0; 162235368Sgnn cpustart[cpu] = timestamp; 163235368Sgnn } 164235368Sgnn 165235368Sgnn 166235368Sgnn profile:::tick-1sec 167235368Sgnn { 168235368Sgnn secs--; 169235368Sgnn } 170235368Sgnn 171235368Sgnn /* Print time */ 172235368Sgnn profile:::tick-1sec 173235368Sgnn /secs == 0/ 174235368Sgnn { 175235368Sgnn OPT_time ? printf("%Y,\n", walltimestamp) : 1; 176235368Sgnn printf("%16s %16s\n", "THREADS", "TIME (ns)"); 177235368Sgnn } 178235368Sgnn 179235368Sgnn /* Print report */ 180235368Sgnn profile:::tick-1sec 181235368Sgnn /secs == 0/ 182235368Sgnn { 183235368Sgnn OPT_top ? trunc(@Procs, TOP) : 1; 184235368Sgnn printa("%16s %@16d\n", @Procs); 185235368Sgnn trunc(@Procs); 186235368Sgnn secs = INTERVAL; 187235368Sgnn counts--; 188235368Sgnn } 189235368Sgnn 190235368Sgnn /* End of program */ 191235368Sgnn profile:::tick-1sec 192235368Sgnn /counts == 0/ 193235368Sgnn { 194235368Sgnn exit(0); 195235368Sgnn } 196235368Sgnn 197235368Sgnn /* cleanup for Ctrl-C */ 198235368Sgnn dtrace:::END 199235368Sgnn { 200235368Sgnn trunc(@Procs); 201235368Sgnn } 202235368Sgnn' 203235368Sgnn 204