#!/usr/bin/ksh
#
# topsyscall - display top syscalls by syscall name.
# Written using DTrace (Solaris 10 3/05).
#
# This program continually prints a report of the top system calls,
# and refreshes the display every 1 second or as specified at the
# command line.
#
# $Id: topsyscall 3 2007-08-01 10:50:08Z brendan $
#
# USAGE: topsyscall [-Cs] [interval [count]]
#
# -C # don't clear the screen
# -s # print per second values
#
# FIELDS:
# load avg load averages, see uptime(1)
# syscalls total syscalls in this interval
# syscalls/s syscalls per second
# SYSCALL system call name
# COUNT total syscalls in this interval
# COUNT/s syscalls per second
#
# INSPIRATION: top(1) by William LeFebvre
#
# COPYRIGHT: Copyright (c) 2005, 2006 Brendan Gregg.
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License, Version 1.0 only
# (the "License"). You may not use this file except in compliance
# with the License.
#
# You can obtain a copy of the license at Docs/cddl1.txt
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# CDDL HEADER END
#
# 13-Jun-2005 Brendan Gregg Created this.
# 20-Apr-2006 " " Last update.
#
##############################
# --- Process Arguments ---
#
### Default variables
count=-1; interval=1; opt_persec=0; opt_clear=1
### Process options
while getopts Chs name
do
case $name in
C) opt_clear=0 ;;
s) opt_persec=1 ;;
h|?) cat <<-END >&2
USAGE: topsyscall [-s] [interval [count]]
-C # don't clear the screen
-s # print per second values
eg,
topsyscall # default, 1 second updates
topsyscall 5 # 5 second updates
END
exit 1
esac
done
shift $(( $OPTIND - 1 ))
### option logic
if [[ "$1" > 0 ]]; then
interval=$1; shift
fi
if [[ "$1" > 0 ]]; then
count=$1; shift
fi
if (( opt_clear )); then
clearstr=`clear`
else
clearstr=.
fi
#################################
# --- Main Program, DTrace ---
#
/usr/sbin/dtrace -n '
#pragma D option quiet
#pragma D option destructive
/* constants */
inline int OPT_clear = '$opt_clear';
inline int OPT_persec = '$opt_persec';
inline int INTERVAL = '$interval';
inline int COUNTER = '$count';
inline int SCREEN = 20;
inline string CLEAR = "'$clearstr'";
/* variables */
dtrace:::BEGIN
{
secs = INTERVAL;
counts = COUNTER;
printf("Tracing... Please wait.\n");
}
/* record syscall event */
syscall:::entry
{
@Name[probefunc] = count();
@Total = count();
}
/* timer */
profile:::tick-1sec
{
secs--;
}
/* update screen */
profile:::tick-1sec
/secs == 0/
{
/* fetch load averages */
this->load1a = `hp_avenrun[0] / 65536;
this->load5a = `hp_avenrun[1] / 65536;
this->load15a = `hp_avenrun[2] / 65536;
this->load1b = ((`hp_avenrun[0] % 65536) * 100) / 65536;
this->load5b = ((`hp_avenrun[1] % 65536) * 100) / 65536;
this->load15b = ((`hp_avenrun[2] % 65536) * 100) / 65536;
/* clear screen */
OPT_clear ? printf("%s", CLEAR) : 1;
/* print load average */
printf("%Y, load average: %d.%02d, %d.%02d, %d.%02d",
walltimestamp, this->load1a, this->load1b, this->load5a,
this->load5b, this->load15a, this->load15b);
/* calculate per second values if needed */
OPT_persec ? normalize(@Total, INTERVAL) : 1;
OPT_persec ? normalize(@Name, INTERVAL) : 1;
/* print syscall count */
printf(" %s: ", OPT_persec ? "syscalls/s" : "syscalls");
printa("%@d\n",@Total);
/* print report */
trunc(@Name, SCREEN);
printf("\n %-25s %12s\n", "SYSCALL",
OPT_persec ? "COUNT/s" : "COUNT");
printa(" %-25s %@12d\n", @Name);
printf("\n");
/* reset variables */
trunc(@Name);
clear(@Total);
secs = INTERVAL;
counts--;
}
/*
* End of program
*/
profile:::tick-1sec
/counts == 0/
{
exit(0);
}
/*
* Cleanup for Ctrl-C
*/
dtrace:::END
{
trunc(@Name);
trunc(@Total);
}
'