Home | History | Annotate | Line # | Download | only in Bin
      1 #!/usr/bin/ksh
      2 #
      3 # iopending - Print a plot for the number of pending disk I/O events.
      4 #             Written using DTrace (Solaris 10 3/05).
      5 #
      6 # This is measuring disk events that have made it past system caches.
      7 # By plotting a distribution graph of the number of pending events, the
      8 # "serialness" or "parallelness" of disk behaviour can be distinguished.
      9 #
     10 # $Id: iopending,v 1.1.1.1 2015/09/30 22:01:07 christos Exp $
     11 #
     12 # USAGE:	iopending [-c] [-d device] [-f filename] 
     13 #		          [-m mount_point] [interval [count]]
     14 #
     15 #		-c		# clear the screen
     16 #		-d device	# instance name to snoop (eg, dad0)
     17 #		-f filename	# full pathname of file to snoop
     18 #		-m mount_point	# this FS only (will skip raw events)
     19 #	eg,
     20 #		iopending   	# default output, 5 second intervals
     21 #		iopending 1  	# 1 second samples
     22 #		iopending -c	# clear the screen
     23 #		iopending 5 12	# print 12 x 5 second samples
     24 # 	
     25 # FIELDS:
     26 #		value		number of pending events, 0 == idle
     27 #		count		number of samples @ 1000 Hz
     28 #		load		1 min load average
     29 #		disk_r		total disk read Kbytes for sample
     30 #		disk_w		total disk write Kbytes for sample
     31 # 
     32 # SEE ALSO: iosnoop, iotop
     33 #
     34 # IDEA: Dr Rex di Bona (Sydney, Australia)
     35 #
     36 # COPYRIGHT: Copyright (c) 2005, 2006 Brendan Gregg.
     37 #
     38 # CDDL HEADER START
     39 #
     40 #  The contents of this file are subject to the terms of the
     41 #  Common Development and Distribution License, Version 1.0 only
     42 #  (the "License").  You may not use this file except in compliance
     43 #  with the License.
     44 #
     45 #  You can obtain a copy of the license at Docs/cddl1.txt
     46 #  or http://www.opensolaris.org/os/licensing.
     47 #  See the License for the specific language governing permissions
     48 #  and limitations under the License.
     49 #
     50 # CDDL HEADER END
     51 #
     52 # Author: Brendan Gregg  [Sydney, Australia]
     53 #
     54 # 01-Nov-2005	Brendan Gregg	Created this.
     55 # 20-Apr-2006	   "      "	Last update.
     56 #
     57 
     58 
     59 ##############################
     60 # --- Process Arguments ---
     61 #
     62 
     63 ### default variables
     64 opt_device=0; opt_file=0; opt_mount=0; opt_clear=0; 
     65 opt_def=1; filter=0; device=.; filename=.; mount=.
     66 interval=5; count=-1
     67 
     68 ### process options
     69 while getopts cd:f:hm: name
     70 do
     71 	case $name in
     72 	c)	opt_clear=1 ;;
     73 	d)	opt_device=1; device=$OPTARG ;;
     74 	f)	opt_file=1; filename=$OPTARG ;;
     75 	m)	opt_mount=1; mount=$OPTARG ;;
     76 	h|?)	cat <<-END >&2
     77 		USAGE: iopending [-c] [-d device] [-f filename]
     78 		                 [-m mount_point] [interval [count]]
     79  
     80 		                -c              # clear the screen
     81 		                -d device       # instance name to snoop 
     82 		                -f filename     # snoop this file only
     83 		                -m mount_point  # this FS only 
     84 		   eg,
     85 		        iopending         # default output, 5 second samples
     86 		        iopending 1       # 1 second samples
     87 		        iopending -m /    # snoop events on filesystem / only
     88 		        iopending 5 12    # print 12 x 5 second samples
     89 		END
     90 		exit 1
     91 	esac
     92 done
     93 
     94 shift $(( $OPTIND - 1 ))
     95 
     96 ### option logic
     97 if [[ "$1" > 0 ]]; then
     98         interval=$1; shift
     99 fi
    100 if [[ "$1" > 0 ]]; then
    101         count=$1; shift
    102 fi
    103 if (( opt_device || opt_mount || opt_file )); then
    104 	filter=1
    105 fi
    106 if (( opt_clear )); then
    107         clearstr=`clear`
    108 else
    109         clearstr=.
    110 fi
    111 
    112 
    113 
    114 #################################
    115 # --- Main Program, DTrace ---
    116 #
    117 /usr/sbin/dtrace -n '
    118  /*
    119   * Command line arguments
    120   */
    121  inline int OPT_def 	= '$opt_def';
    122  inline int OPT_clear 	= '$opt_clear';
    123  inline int OPT_device 	= '$opt_device';
    124  inline int OPT_mount 	= '$opt_mount';
    125  inline int OPT_file 	= '$opt_file';
    126  inline int INTERVAL 	= '$interval';
    127  inline int COUNTER 	= '$count';
    128  inline int FILTER 	= '$filter';
    129  inline string DEVICE 	= "'$device'";
    130  inline string FILENAME = "'$filename'";
    131  inline string MOUNT 	= "'$mount'";
    132  inline string CLEAR 	= "'$clearstr'";
    133 
    134  inline int MAX_PENDING = 32;	/* max pending value */
    135  
    136  #pragma D option quiet
    137 
    138  /*
    139   * Print header
    140   */
    141  dtrace:::BEGIN 
    142  {
    143         /* starting values */
    144         counts = COUNTER;
    145         secs = INTERVAL;
    146         disk_r = 0;
    147         disk_w = 0;
    148         pending = 0;
    149 
    150         printf("Tracing... Please wait.\n");
    151  }
    152 
    153  /*
    154   * Check event is being traced
    155   */
    156  io:genunix::start,
    157  io:genunix::done 
    158  { 
    159 	/* default is to trace unless filtering, */
    160 	this->ok = FILTER ? 0 : 1;
    161 
    162 	/* check each filter, */
    163 	(OPT_device == 1 && DEVICE == args[1]->dev_statname)? this->ok = 1 : 1;
    164 	(OPT_file == 1 && FILENAME == args[2]->fi_pathname) ? this->ok = 1 : 1;
    165 	(OPT_mount == 1 && MOUNT == args[2]->fi_mount)  ? this->ok = 1 : 1;
    166  }
    167 
    168  /*
    169   * Store entry details
    170   */
    171  io:genunix::start
    172  /this->ok/
    173  {
    174 	/* track bytes */
    175 	disk_r += args[0]->b_flags & B_READ ? args[0]->b_bcount : 0;
    176 	disk_w += args[0]->b_flags & B_READ ? 0 : args[0]->b_bcount;
    177 
    178 	/* increase event pending count */
    179 	pending++;
    180  }
    181 
    182  /*
    183   * Process and Print completion
    184   */
    185  io:genunix::done
    186  /this->ok/
    187  {
    188 	/* decrease event pending count */
    189 	pending--;
    190  }
    191 
    192  /*
    193   * Prevent pending from underflowing
    194   * this can happen if this program is started during disk events.
    195   */
    196  io:genunix::done
    197  /pending < 0/
    198  {
    199 	pending = 0;
    200  }
    201 
    202  /*
    203   * Timer
    204   */
    205  profile:::tick-1sec
    206  {
    207 	secs--;
    208  }
    209 
    210  profile:::profile-1000hz
    211  {
    212 	@out = lquantize(pending, 0, MAX_PENDING, 1);
    213  }
    214 
    215  /*
    216   * Print Report
    217   */
    218  profile:::tick-1sec
    219  /secs == 0/
    220  {
    221 	/* fetch 1 min load average */
    222 	this->load1a  = `hp_avenrun[0] / 65536;
    223 	this->load1b  = ((`hp_avenrun[0] % 65536) * 100) / 65536;
    224 
    225 	/* convert counters to Kbytes */
    226 	disk_r /= 1024;
    227 	disk_w /= 1024;
    228 
    229 	/* print status */
    230 	OPT_clear ? printf("%s", CLEAR) : 1;
    231 	printf("%Y,  load: %d.%02d,  disk_r: %6d KB,  disk_w: %6d KB",
    232 	    walltimestamp, this->load1a, this->load1b, disk_r, disk_w);
    233 
    234 	/* print output */
    235 	printa(@out);
    236 
    237 	/* clear data */
    238 	trunc(@out);
    239 	disk_r = 0;
    240 	disk_w = 0;
    241 	secs = INTERVAL;
    242 	counts--;
    243  }
    244 
    245  /*
    246   * End of program
    247   */
    248  profile:::tick-1sec
    249  /counts == 0/
    250  {
    251 	exit(0);
    252  }
    253 
    254  /*
    255   * Cleanup for Ctrl-C
    256   */
    257  dtrace:::END
    258  {
    259 	trunc(@out);
    260  }
    261 '
    262