diff options
Diffstat (limited to 'Disk/iopending')
-rwxr-xr-x | Disk/iopending | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/Disk/iopending b/Disk/iopending new file mode 100755 index 000000000000..ef9d4da7a625 --- /dev/null +++ b/Disk/iopending @@ -0,0 +1,261 @@ +#!/usr/bin/ksh +# +# iopending - Print a plot for the number of pending disk I/O events. +# Written using DTrace (Solaris 10 3/05). +# +# This is measuring disk events that have made it past system caches. +# By plotting a distribution graph of the number of pending events, the +# "serialness" or "parallelness" of disk behaviour can be distinguished. +# +# $Id: iopending 3 2007-08-01 10:50:08Z brendan $ +# +# USAGE: iopending [-c] [-d device] [-f filename] +# [-m mount_point] [interval [count]] +# +# -c # clear the screen +# -d device # instance name to snoop (eg, dad0) +# -f filename # full pathname of file to snoop +# -m mount_point # this FS only (will skip raw events) +# eg, +# iopending # default output, 5 second intervals +# iopending 1 # 1 second samples +# iopending -c # clear the screen +# iopending 5 12 # print 12 x 5 second samples +# +# FIELDS: +# value number of pending events, 0 == idle +# count number of samples @ 1000 Hz +# load 1 min load average +# disk_r total disk read Kbytes for sample +# disk_w total disk write Kbytes for sample +# +# SEE ALSO: iosnoop, iotop +# +# IDEA: Dr Rex di Bona (Sydney, Australia) +# +# 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 +# +# Author: Brendan Gregg [Sydney, Australia] +# +# 01-Nov-2005 Brendan Gregg Created this. +# 20-Apr-2006 " " Last update. +# + + +############################## +# --- Process Arguments --- +# + +### default variables +opt_device=0; opt_file=0; opt_mount=0; opt_clear=0; +opt_def=1; filter=0; device=.; filename=.; mount=. +interval=5; count=-1 + +### process options +while getopts cd:f:hm: name +do + case $name in + c) opt_clear=1 ;; + d) opt_device=1; device=$OPTARG ;; + f) opt_file=1; filename=$OPTARG ;; + m) opt_mount=1; mount=$OPTARG ;; + h|?) cat <<-END >&2 + USAGE: iopending [-c] [-d device] [-f filename] + [-m mount_point] [interval [count]] + + -c # clear the screen + -d device # instance name to snoop + -f filename # snoop this file only + -m mount_point # this FS only + eg, + iopending # default output, 5 second samples + iopending 1 # 1 second samples + iopending -m / # snoop events on filesystem / only + iopending 5 12 # print 12 x 5 second samples + 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_device || opt_mount || opt_file )); then + filter=1 +fi +if (( opt_clear )); then + clearstr=`clear` +else + clearstr=. +fi + + + +################################# +# --- Main Program, DTrace --- +# +/usr/sbin/dtrace -n ' + /* + * Command line arguments + */ + inline int OPT_def = '$opt_def'; + inline int OPT_clear = '$opt_clear'; + inline int OPT_device = '$opt_device'; + inline int OPT_mount = '$opt_mount'; + inline int OPT_file = '$opt_file'; + inline int INTERVAL = '$interval'; + inline int COUNTER = '$count'; + inline int FILTER = '$filter'; + inline string DEVICE = "'$device'"; + inline string FILENAME = "'$filename'"; + inline string MOUNT = "'$mount'"; + inline string CLEAR = "'$clearstr'"; + + inline int MAX_PENDING = 32; /* max pending value */ + + #pragma D option quiet + + /* + * Print header + */ + dtrace:::BEGIN + { + /* starting values */ + counts = COUNTER; + secs = INTERVAL; + disk_r = 0; + disk_w = 0; + pending = 0; + + printf("Tracing... Please wait.\n"); + } + + /* + * Check event is being traced + */ + io:genunix::start, + io:genunix::done + { + /* default is to trace unless filtering, */ + this->ok = FILTER ? 0 : 1; + + /* check each filter, */ + (OPT_device == 1 && DEVICE == args[1]->dev_statname)? this->ok = 1 : 1; + (OPT_file == 1 && FILENAME == args[2]->fi_pathname) ? this->ok = 1 : 1; + (OPT_mount == 1 && MOUNT == args[2]->fi_mount) ? this->ok = 1 : 1; + } + + /* + * Store entry details + */ + io:genunix::start + /this->ok/ + { + /* track bytes */ + disk_r += args[0]->b_flags & B_READ ? args[0]->b_bcount : 0; + disk_w += args[0]->b_flags & B_READ ? 0 : args[0]->b_bcount; + + /* increase event pending count */ + pending++; + } + + /* + * Process and Print completion + */ + io:genunix::done + /this->ok/ + { + /* decrease event pending count */ + pending--; + } + + /* + * Prevent pending from underflowing + * this can happen if this program is started during disk events. + */ + io:genunix::done + /pending < 0/ + { + pending = 0; + } + + /* + * Timer + */ + profile:::tick-1sec + { + secs--; + } + + profile:::profile-1000hz + { + @out = lquantize(pending, 0, MAX_PENDING, 1); + } + + /* + * Print Report + */ + profile:::tick-1sec + /secs == 0/ + { + /* fetch 1 min load average */ + this->load1a = `hp_avenrun[0] / 65536; + this->load1b = ((`hp_avenrun[0] % 65536) * 100) / 65536; + + /* convert counters to Kbytes */ + disk_r /= 1024; + disk_w /= 1024; + + /* print status */ + OPT_clear ? printf("%s", CLEAR) : 1; + printf("%Y, load: %d.%02d, disk_r: %6d KB, disk_w: %6d KB", + walltimestamp, this->load1a, this->load1b, disk_r, disk_w); + + /* print output */ + printa(@out); + + /* clear data */ + trunc(@out); + disk_r = 0; + disk_w = 0; + secs = INTERVAL; + counts--; + } + + /* + * End of program + */ + profile:::tick-1sec + /counts == 0/ + { + exit(0); + } + + /* + * Cleanup for Ctrl-C + */ + dtrace:::END + { + trunc(@out); + } +' |