]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - cddl/contrib/dtracetoolkit/Disk/iopending
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[FreeBSD/stable/10.git] / cddl / contrib / dtracetoolkit / Disk / iopending
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 3 2007-08-01 10:50:08Z brendan $
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 '