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