cpudists revision 235368
165557Sjasone#!/usr/bin/sh
265557Sjasone#
365557Sjasone# cpudists - print CPU time distributions by Kernel/Idle/Processes.
465557Sjasone#            Written using DTrace (Solaris 10 3/05).
565557Sjasone#
665557Sjasone# $Id: cpudists 3 2007-08-01 10:50:08Z brendan $
765557Sjasone#
865557Sjasone# USAGE:	cpudists [-ahV] [-t top] [interval [count]]
965557Sjasone#
1065557Sjasone#		-a              # print all processes
1165557Sjasone#		-V              # don't print timestamps
1265557Sjasone#		-t num          # print top num  only
1365557Sjasone#  eg,
1465557Sjasone#		cpudists 1      # print every 1 second
1565557Sjasone#		cpudists -a 10  # print all processes every 10 secs
1665557Sjasone#
1765557Sjasone#
1865557Sjasone# FIELDS: 
1965557Sjasone#		value           The following or the process name,
2065557Sjasone#		IDLE            Idle time - CPU running idle thread
2165557Sjasone#		KERNEL          Kernel time - Kernel servicing interrupts, ...
2265557Sjasone#		PROCESS         Process time - PIDs running on the system
2365557Sjasone#		count           Number of occurances at least this duration (ns)
2465557Sjasone#
2565557Sjasone# NOTES:
2665557Sjasone# * This takes into account multiple CPU servers, the total 
2765557Sjasone# seconds consumed will be a multiple of the CPU count and interval.
2865557Sjasone#
2967352Sjhb# SEE ALSO: cputimes
3065557Sjasone#
3165557Sjasone# COPYRIGHT: Copyright (c) 2005 Brendan Gregg.
3265557Sjasone#
3365557Sjasone# CDDL HEADER START
3472200Sbmilekic#
3572200Sbmilekic#  The contents of this file are subject to the terms of the
3672200Sbmilekic#  Common Development and Distribution License, Version 1.0 only
3772200Sbmilekic#  (the "License").  You may not use this file except in compliance
3872200Sbmilekic#  with the License.
3965557Sjasone#
4065557Sjasone#  You can obtain a copy of the license at Docs/cddl1.txt
4165557Sjasone#  or http://www.opensolaris.org/os/licensing.
4265557Sjasone#  See the License for the specific language governing permissions
4365557Sjasone#  and limitations under the License.
4465557Sjasone#
4565557Sjasone# CDDL HEADER END
4665557Sjasone#
4765557Sjasone# Author: Brendan Gregg  [Sydney, Australia]
4865557Sjasone#
4965557Sjasone# 27-Apr-2005   Brendan Gregg   Created this.
5065557Sjasone# 22-Sep-2005	   "      "	Fixed key corruption bug.
5165557Sjasone# 22-Sep-2005	   "      "	Last update.
5265557Sjasone#
5365557Sjasone
5465557Sjasone
5565557Sjasone##############################
5665557Sjasone# --- Process Arguments ---
5765557Sjasone#
5868790Sjhbopt_all=0; opt_time=1; opt_top=0; top=0; interval=1; count=1
5967676Sjhb
6065557Sjasonewhile getopts aht:V name
6167352Sjhbdo
6267352Sjhb        case $name in
6376166Smarkm        a)      opt_all=1 ;;
6467352Sjhb        V)      opt_time=0 ;;
6574912Sjhb        t)      opt_top=1; top=$OPTARG ;;
6665557Sjasone        h|?)    cat <<-END >&2
6767676Sjhb		USAGE: cpudists [-ahV] [-t top] [interval [count]]
6865557Sjasone		       cpudists                # default output
6967352Sjhb		               -a              # print all processes
7065557Sjasone		               -V              # don't print times
7165557Sjasone		               -t num          # print top num only
7267352Sjhb		END
7367352Sjhb		exit 1
7467352Sjhb        esac
7565557Sjasonedone
7667352Sjhbshift `expr $OPTIND - 1`
7768790Sjhb
7868790Sjhbif [ "$1" -gt 0 ]; then
7967352Sjhb        interval=$1; count=-1; shift
8067352Sjhbfi
8167352Sjhbif [ "$1" -gt 0 ]; then
8265557Sjasone	count=$1; shift
8372200Sbmilekicfi
8471352Sjasone
8572200Sbmilekic
8671352Sjasone#################################
8772200Sbmilekic# --- Main Program, DTrace ---
8872200Sbmilekic#
8971352Sjasone/usr/sbin/dtrace -n '
9072376Sjake #pragma D option quiet
9171352Sjasone
9271352Sjasone /*
9374912Sjhb  * Command line arguments
9471352Sjasone  */
9574912Sjhb inline int OPT_all    = '$opt_all';
9674912Sjhb inline int OPT_time   = '$opt_time';
9774912Sjhb inline int OPT_top    = '$opt_top';
9874912Sjhb inline int TOP        = '$top';
9974912Sjhb inline int INTERVAL   = '$interval';
10074912Sjhb inline int COUNTER    = '$count';
10174912Sjhb
10274912Sjhb /* Initialise variables */
10371352Sjasone dtrace:::BEGIN
10471352Sjasone {
10572200Sbmilekic	cpustart[cpu] = 0;
10672200Sbmilekic	counts = COUNTER;
10771352Sjasone	secs = INTERVAL;
10867352Sjhb }
10967352Sjhb
11067352Sjhb /* Flag this thread as idle */
11167352Sjhb sysinfo:unix:idle_enter:idlethread
11272376Sjake {
11367352Sjhb	idle[cpu] = 1;
11467352Sjhb }
11569376Sjhb
11667352Sjhb /* Save kernel time between running threads */
11767352Sjhb sched:::on-cpu 
11867352Sjhb /cpustart[cpu]/
11967352Sjhb {
12067352Sjhb	this->elapsed = timestamp - cpustart[cpu];
12167352Sjhb	@Procs["KERNEL"] = quantize(this->elapsed);
12267352Sjhb }
12367352Sjhb
12467352Sjhb /* Save the elapsed time of a thread */
12567352Sjhb sched:::off-cpu,
12667352Sjhb sched:::remain-cpu,
12767352Sjhb profile:::profile-1sec
12867352Sjhb /cpustart[cpu]/
12967352Sjhb {
13072200Sbmilekic	/* determine the name for this thread */
13167352Sjhb	program[cpu] = pid == 0 ? idle[cpu] ? "IDLE" : "KERNEL" :
13269376Sjhb	    OPT_all ? execname : "PROCESS";
13372376Sjake
13467352Sjhb	/* save elapsed */
13569376Sjhb	this->elapsed = timestamp - cpustart[cpu];
13667352Sjhb	@Procs[program[cpu]] = quantize(this->elapsed);
13769376Sjhb	cpustart[cpu] = timestamp;
13869376Sjhb }
13969376Sjhb
14069376Sjhb /* Record the start time of a thread */
14169376Sjhb sched:::on-cpu,
14267352Sjhb sched:::remain-cpu
14367352Sjhb {
14472836Sjhb	idle[cpu] = 0;
14575468Smarkm	cpustart[cpu] = timestamp;
14667352Sjhb }
14767352Sjhb
14872376Sjake profile:::tick-1sec
14973912Sjhb {
15067352Sjhb	secs--;
15173912Sjhb }
15273912Sjhb
15373912Sjhb /* Print time */
15473912Sjhb profile:::tick-1sec 
15573912Sjhb /secs == 0 && OPT_time/ 
15673912Sjhb { 
15773912Sjhb	printf("%Y,\n", walltimestamp);
15867352Sjhb }
15967352Sjhb
16067352Sjhb /* Print report */
16167352Sjhb profile:::tick-1sec 
16267352Sjhb /secs == 0/ 
16367352Sjhb { 
16467352Sjhb	OPT_top ? trunc(@Procs, TOP) : 1;
16567352Sjhb	printa("%16s %@16d\n", @Procs);
16667352Sjhb	trunc(@Procs);
16767352Sjhb	secs = INTERVAL;
16867352Sjhb	counts--;
16969376Sjhb }
17067352Sjhb
17169376Sjhb /* End of program */
17269376Sjhb profile:::tick-1sec 
17369376Sjhb /counts == 0/ 
17474912Sjhb {
17567352Sjhb	exit(0);
17667352Sjhb }
17767352Sjhb
17867352Sjhb /* cleanup for Ctrl-C */
17967352Sjhb dtrace:::END
18067352Sjhb {
18167352Sjhb	trunc(@Procs);
18267352Sjhb }
18367352Sjhb'
18467352Sjhb
18567352Sjhb