262 lines
5.7 KiB
Bash
Executable File
262 lines
5.7 KiB
Bash
Executable File
#!/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,v 1.1.1.1 2015/09/30 22:01:07 christos Exp $
|
|
#
|
|
# 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);
|
|
}
|
|
'
|