1N/A#!/usr/bin/sh
1N/A#
1N/A# cpudists - print CPU time distributions by Kernel/Idle/Processes.
1N/A# Written using DTrace (Solaris 10 3/05).
1N/A#
1N/A# $Id: cpudists 3 2007-08-01 10:50:08Z brendan $
1N/A#
1N/A# USAGE: cpudists [-ahV] [-t top] [interval [count]]
1N/A#
1N/A# -a # print all processes
1N/A# -V # don't print timestamps
1N/A# -t num # print top num only
1N/A# eg,
1N/A# cpudists 1 # print every 1 second
1N/A# cpudists -a 10 # print all processes every 10 secs
1N/A#
1N/A#
1N/A# FIELDS:
1N/A# value The following or the process name,
1N/A# IDLE Idle time - CPU running idle thread
1N/A# KERNEL Kernel time - Kernel servicing interrupts, ...
1N/A# PROCESS Process time - PIDs running on the system
1N/A# count Number of occurances at least this duration (ns)
1N/A#
1N/A# NOTES:
1N/A# * This takes into account multiple CPU servers, the total
1N/A# seconds consumed will be a multiple of the CPU count and interval.
1N/A#
1N/A# SEE ALSO: cputimes
1N/A#
1N/A# COPYRIGHT: Copyright (c) 2005 Brendan Gregg.
1N/A#
1N/A# CDDL HEADER START
1N/A#
1N/A# The contents of this file are subject to the terms of the
1N/A# Common Development and Distribution License, Version 1.0 only
1N/A# (the "License"). You may not use this file except in compliance
1N/A# with the License.
1N/A#
1N/A# You can obtain a copy of the license at Docs/cddl1.txt
1N/A# or http://www.opensolaris.org/os/licensing.
1N/A# See the License for the specific language governing permissions
1N/A# and limitations under the License.
1N/A#
1N/A# CDDL HEADER END
1N/A#
1N/A# Author: Brendan Gregg [Sydney, Australia]
1N/A#
1N/A# 27-Apr-2005 Brendan Gregg Created this.
1N/A# 22-Sep-2005 " " Fixed key corruption bug.
1N/A# 22-Sep-2005 " " Last update.
1N/A#
1N/A
1N/A
1N/A##############################
1N/A# --- Process Arguments ---
1N/A#
1N/Aopt_all=0; opt_time=1; opt_top=0; top=0; interval=1; count=1
1N/A
1N/Awhile getopts aht:V name
1N/Ado
1N/A case $name in
1N/A a) opt_all=1 ;;
1N/A V) opt_time=0 ;;
1N/A t) opt_top=1; top=$OPTARG ;;
1N/A h|?) cat <<-END >&2
1N/A USAGE: cpudists [-ahV] [-t top] [interval [count]]
1N/A cpudists # default output
1N/A -a # print all processes
1N/A -V # don't print times
1N/A -t num # print top num only
1N/A END
1N/A exit 1
1N/A esac
1N/Adone
1N/Ashift `expr $OPTIND - 1`
1N/A
1N/Aif [ "$1" -gt 0 ]; then
1N/A interval=$1; count=-1; shift
1N/Afi
1N/Aif [ "$1" -gt 0 ]; then
1N/A count=$1; shift
1N/Afi
1N/A
1N/A
1N/A#################################
1N/A# --- Main Program, DTrace ---
1N/A#
1N/A/usr/sbin/dtrace -n '
1N/A #pragma D option quiet
1N/A
1N/A /*
1N/A * Command line arguments
1N/A */
1N/A inline int OPT_all = '$opt_all';
1N/A inline int OPT_time = '$opt_time';
1N/A inline int OPT_top = '$opt_top';
1N/A inline int TOP = '$top';
1N/A inline int INTERVAL = '$interval';
1N/A inline int COUNTER = '$count';
1N/A
1N/A /* Initialise variables */
1N/A dtrace:::BEGIN
1N/A {
1N/A cpustart[cpu] = 0;
1N/A counts = COUNTER;
1N/A secs = INTERVAL;
1N/A }
1N/A
1N/A /* Flag this thread as idle */
1N/A sysinfo:unix:idle_enter:idlethread
1N/A {
1N/A idle[cpu] = 1;
1N/A }
1N/A
1N/A /* Save kernel time between running threads */
1N/A sched:::on-cpu
1N/A /cpustart[cpu]/
1N/A {
1N/A this->elapsed = timestamp - cpustart[cpu];
1N/A @Procs["KERNEL"] = quantize(this->elapsed);
1N/A }
1N/A
1N/A /* Save the elapsed time of a thread */
1N/A sched:::off-cpu,
1N/A sched:::remain-cpu,
1N/A profile:::profile-1sec
1N/A /cpustart[cpu]/
1N/A {
1N/A /* determine the name for this thread */
1N/A program[cpu] = pid == 0 ? idle[cpu] ? "IDLE" : "KERNEL" :
1N/A OPT_all ? execname : "PROCESS";
1N/A
1N/A /* save elapsed */
1N/A this->elapsed = timestamp - cpustart[cpu];
1N/A @Procs[program[cpu]] = quantize(this->elapsed);
1N/A cpustart[cpu] = timestamp;
1N/A }
1N/A
1N/A /* Record the start time of a thread */
1N/A sched:::on-cpu,
1N/A sched:::remain-cpu
1N/A {
1N/A idle[cpu] = 0;
1N/A cpustart[cpu] = timestamp;
1N/A }
1N/A
1N/A profile:::tick-1sec
1N/A {
1N/A secs--;
1N/A }
1N/A
1N/A /* Print time */
1N/A profile:::tick-1sec
1N/A /secs == 0 && OPT_time/
1N/A {
1N/A printf("%Y,\n", walltimestamp);
1N/A }
1N/A
1N/A /* Print report */
1N/A profile:::tick-1sec
1N/A /secs == 0/
1N/A {
1N/A OPT_top ? trunc(@Procs, TOP) : 1;
1N/A printa("%16s %@16d\n", @Procs);
1N/A trunc(@Procs);
1N/A secs = INTERVAL;
1N/A counts--;
1N/A }
1N/A
1N/A /* End of program */
1N/A profile:::tick-1sec
1N/A /counts == 0/
1N/A {
1N/A exit(0);
1N/A }
1N/A
1N/A /* cleanup for Ctrl-C */
1N/A dtrace:::END
1N/A {
1N/A trunc(@Procs);
1N/A }
1N/A'
1N/A