#!/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); } '