]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - cddl/contrib/dtracetoolkit/iopattern
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[FreeBSD/stable/10.git] / cddl / contrib / dtracetoolkit / iopattern
1 #!/usr/bin/ksh
2 #
3 # iopattern - print disk I/O pattern.
4 #             Written using DTrace (Solaris 10 3/05).
5 #
6 # This prints details on the I/O access pattern for the disks, such as
7 # percentage of events that were of a random or sequential nature.
8 # By default totals for all disks are printed.
9 #
10 # $Id: iopattern 65 2007-10-04 11:09:40Z brendan $
11 #
12 # USAGE:        iopattern [-v] [-d device] [-f filename] [-m mount_point] 
13 #                         [interval [count]]
14 #
15 #                      -v               # print timestamp, string
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 #               iopattern       # default output, 1 second intervals
21 #               iopattern 10    # 10 second samples
22 #               iopattern 5 12  # print 12 x 5 second samples
23 #               iopattern -m /  # snoop events on filesystem / only
24 #       
25 # FIELDS:
26 #               %RAN            percentage of events of a random nature
27 #               %SEQ            percentage of events of a sequential nature
28 #               COUNT           number of I/O events
29 #               MIN             minimum I/O event size
30 #               MAX             maximum I/O event size
31 #               AVG             average I/O event size
32 #               KR              total kilobytes read during sample
33 #               KW              total kilobytes written during sample
34 #               DEVICE          device name
35 #               MOUNT           mount point
36 #               FILE            filename
37 #               TIME            timestamp, string
38
39 # NOTES:
40 #
41 #  An event is considered random when the heads seek. This program prints
42 #  the percentage of events that are random. The size of the seek is not
43 #  measured - it's either random or not.
44 #
45 # SEE ALSO: iosnoop, iotop
46
47 # IDEA: Ryan Matteson
48 #
49 # COPYRIGHT: Copyright (c) 2005 Brendan Gregg.
50 #
51 # CDDL HEADER START
52 #
53 #  The contents of this file are subject to the terms of the
54 #  Common Development and Distribution License, Version 1.0 only
55 #  (the "License").  You may not use this file except in compliance
56 #  with the License.
57 #
58 #  You can obtain a copy of the license at Docs/cddl1.txt
59 #  or http://www.opensolaris.org/os/licensing.
60 #  See the License for the specific language governing permissions
61 #  and limitations under the License.
62 #
63 # CDDL HEADER END
64 #
65 # Author: Brendan Gregg  [Sydney, Australia]
66 #
67 # 25-Jul-2005   Brendan Gregg   Created this.
68 # 25-Jul-2005      "      "     Last update.
69 #
70
71
72 ##############################
73 # --- Process Arguments ---
74 #
75
76 ### default variables
77 opt_device=0; opt_file=0; opt_mount=0; opt_time=0
78 filter=0; device=.; filename=.; mount=.; interval=1; count=-1
79
80 ### process options
81 while getopts d:f:hm:v name
82 do
83         case $name in
84         d)      opt_device=1; device=$OPTARG ;;
85         f)      opt_file=1; filename=$OPTARG ;;
86         m)      opt_mount=1; mount=$OPTARG ;;
87         v)      opt_time=1 ;;
88         h|?)    cat <<-END >&2
89                 USAGE: iopattern [-v] [-d device] [-f filename] [-m mount_point]
90                                  [interval [count]]
91  
92                                 -v              # print timestamp
93                                 -d device       # instance name to snoop 
94                                 -f filename     # snoop this file only
95                                 -m mount_point  # this FS only 
96                    eg,
97                         iopattern         # default output, 1 second samples
98                         iopattern 10      # 10 second samples
99                         iopattern 5 12    # print 12 x 5 second samples
100                         iopattern -m /    # snoop events on filesystem / only
101                 END
102                 exit 1
103         esac
104 done
105
106 shift $(( $OPTIND - 1 ))
107
108 ### option logic
109 if [[ "$1" > 0 ]]; then
110         interval=$1; shift
111 fi
112 if [[ "$1" > 0 ]]; then
113         count=$1; shift
114 fi
115 if (( opt_device || opt_mount || opt_file )); then
116         filter=1
117 fi
118
119
120 #################################
121 # --- Main Program, DTrace ---
122 #
123 /usr/sbin/dtrace -n '
124  /*
125   * Command line arguments
126   */
127  inline int OPT_time    = '$opt_time';
128  inline int OPT_device  = '$opt_device';
129  inline int OPT_mount   = '$opt_mount';
130  inline int OPT_file    = '$opt_file';
131  inline int INTERVAL    = '$interval';
132  inline int COUNTER     = '$count';
133  inline int FILTER      = '$filter';
134  inline string DEVICE   = "'$device'";
135  inline string FILENAME = "'$filename'";
136  inline string MOUNT    = "'$mount'";
137  
138  #pragma D option quiet
139
140  int last_loc[string];
141
142  /*
143   * Program start
144   */
145  dtrace:::BEGIN 
146  {
147         /* starting values */
148         diskcnt = 0;
149         diskmin = 0;
150         diskmax = 0;
151         diskran = 0;
152         diskr = 0;
153         diskw = 0;
154         counts = COUNTER;
155         secs = INTERVAL;
156         LINES = 20;
157         line = 0;
158         last_event[""] = 0;
159  }
160
161  /*
162   * Print header
163   */
164  profile:::tick-1sec
165  /line <= 0 /
166  {
167         /* print optional headers */
168         OPT_time   ? printf("%-20s ", "TIME")  : 1;
169         OPT_device ? printf("%-9s ", "DEVICE") : 1;
170         OPT_mount  ? printf("%-12s ", "MOUNT") : 1;
171         OPT_file   ? printf("%-12s ", "FILE") : 1;
172
173         /* print header */
174         printf("%4s %4s %6s %6s %6s %6s %6s %6s\n",
175             "%RAN", "%SEQ", "COUNT", "MIN", "MAX", "AVG", "KR", "KW");
176
177         line = LINES;
178  }
179
180  /*
181   * Check event is being traced
182   */
183  io:genunix::done
184  { 
185         /* default is to trace unless filtering */
186         self->ok = FILTER ? 0 : 1;
187
188         /* check each filter */
189         (OPT_device == 1 && DEVICE == args[1]->dev_statname)? self->ok = 1 : 1;
190         (OPT_file == 1 && FILENAME == args[2]->fi_pathname) ? self->ok = 1 : 1;
191         (OPT_mount == 1 && MOUNT == args[2]->fi_mount)  ? self->ok = 1 : 1;
192  }
193
194  /*
195   * Process and Print completion
196   */
197  io:genunix::done
198  /self->ok/
199  {
200         /*
201          * Save details
202          */
203         this->loc = args[0]->b_blkno * 512;
204         this->pre = last_loc[args[1]->dev_statname];
205         diskr += args[0]->b_flags & B_READ ? args[0]->b_bcount : 0;
206         diskw += args[0]->b_flags & B_READ ? 0 : args[0]->b_bcount;
207         diskran += this->pre == this->loc ? 0 : 1;
208         diskcnt++;
209         diskmin = diskmin == 0 ? args[0]->b_bcount :
210             (diskmin > args[0]->b_bcount ? args[0]->b_bcount : diskmin);
211         diskmax = diskmax < args[0]->b_bcount ? args[0]->b_bcount : diskmax;
212
213         /* save disk location */
214         last_loc[args[1]->dev_statname] = this->loc + args[0]->b_bcount;
215
216         /* cleanup */
217         self->ok = 0;
218  }
219
220  /*
221   * Timer
222   */
223  profile:::tick-1sec
224  {
225         secs--;
226  }
227
228  /*
229   * Print Output
230   */
231  profile:::tick-1sec
232  /secs == 0/
233  {
234         /* calculate diskavg */
235         diskavg = diskcnt > 0 ? (diskr + diskw) / diskcnt : 0;
236
237         /* convert counters to Kbytes */
238         diskr /= 1024;
239         diskw /= 1024;
240
241         /* convert to percentages */
242         diskran = diskcnt == 0 ? 0 : (diskran * 100) / diskcnt;
243         diskseq = diskcnt == 0 ? 0 : 100 - diskran;
244
245         /* print optional fields */
246         OPT_time   ? printf("%-20Y ", walltimestamp) : 1;
247         OPT_device ? printf("%-9s ", DEVICE) : 1;
248         OPT_mount  ? printf("%-12s ", MOUNT) : 1;
249         OPT_file   ? printf("%-12s ", FILENAME) : 1;
250
251         /* print data */
252         printf("%4d %4d %6d %6d %6d %6d %6d %6d\n",
253             diskran, diskseq, diskcnt, diskmin, diskmax, diskavg,
254             diskr, diskw);
255
256         /* clear data */
257         diskmin = 0;
258         diskmax = 0;
259         diskcnt = 0;
260         diskran = 0;
261         diskr = 0;
262         diskw = 0;
263
264         secs = INTERVAL;
265         counts--;
266         line--;
267  }
268
269  /*
270   * End of program
271   */
272  profile:::tick-1sec
273  /counts == 0/
274  {
275         exit(0);
276  }
277 '