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