pfilestat revision 1.1 1 1.1 christos #!/usr/bin/sh
2 1.1 christos #
3 1.1 christos # pfilestat
4 1.1 christos #
5 1.1 christos # This prints I/O statistics for each file descriptor within a process.
6 1.1 christos # In particular, the time break down during read() and write() events is
7 1.1 christos # measured.
8 1.1 christos #
9 1.1 christos # $Id: pfilestat,v 1.1 2015/09/30 22:01:09 christos Exp $
10 1.1 christos #
11 1.1 christos # USAGE: pfilestat [-r|-w] pid
12 1.1 christos #
13 1.1 christos # FIELDS:
14 1.1 christos # STATE microstate: running, sleeping, waitcpu, read, write
15 1.1 christos # FDUM File Descriptor ID
16 1.1 christos # Time Percentage of wallclock time in each STATE
17 1.1 christos # File Name of file, if known
18 1.1 christos #
19 1.1 christos # COPYRIGHT: Copyright (c) 2006 Richard McDougall.
20 1.1 christos #
21 1.1 christos # CDDL HEADER START
22 1.1 christos #
23 1.1 christos # The contents of this file are subject to the terms of the
24 1.1 christos # Common Development and Distribution License, Version 1.0 only
25 1.1 christos # (the "License"). You may not use this file except in compliance
26 1.1 christos # with the License.
27 1.1 christos #
28 1.1 christos # You can obtain a copy of the license at Docs/cddl1.txt
29 1.1 christos # or http://www.opensolaris.org/os/licensing.
30 1.1 christos # See the License for the specific language governing permissions
31 1.1 christos # and limitations under the License.
32 1.1 christos #
33 1.1 christos # CDDL HEADER END
34 1.1 christos #
35 1.1 christos # ToDo:
36 1.1 christos # Trace readv() and writev().
37 1.1 christos #
38 1.1 christos # 20-Feb-2006 Richard McDougall created this.
39 1.1 christos # 24-Feb-2006 Brendan Gregg tweaked code.
40 1.1 christos # 20-Mar-2006 " " tweaked code.
41 1.1 christos # 20-Mar-2006 " " last update.
42 1.1 christos
43 1.1 christos
44 1.1 christos ##############################
45 1.1 christos # --- Process Arguments ---
46 1.1 christos #
47 1.1 christos
48 1.1 christos ### Default variables
49 1.1 christos opt_read=0; opt_write=0
50 1.1 christos
51 1.1 christos ### Process options
52 1.1 christos while getopts hrw name
53 1.1 christos do
54 1.1 christos case $name in
55 1.1 christos r) opt_read=1 ;;
56 1.1 christos w) opt_write=1 ;;
57 1.1 christos h|?) cat <<-END >&2
58 1.1 christos USAGE: pfilestat [-r|-w] pid
59 1.1 christos -r # reads only
60 1.1 christos -w # writes only
61 1.1 christos eg,
62 1.1 christos pfilestat pid # default, r+w counts
63 1.1 christos pfilestat -r pid # read count only
64 1.1 christos END
65 1.1 christos exit 1
66 1.1 christos esac
67 1.1 christos done
68 1.1 christos shift `expr $OPTIND - 1`
69 1.1 christos
70 1.1 christos PID=$1
71 1.1 christos clearstr=`clear`
72 1.1 christos
73 1.1 christos if [ -z "$PID" ]
74 1.1 christos then
75 1.1 christos echo "Must supply pid"
76 1.1 christos exit 1
77 1.1 christos fi
78 1.1 christos
79 1.1 christos ### Option logic
80 1.1 christos if [ $opt_read -eq 0 -a $opt_write -eq 0 ]; then
81 1.1 christos opt_read=1; opt_write=1
82 1.1 christos fi
83 1.1 christos
84 1.1 christos
85 1.1 christos #################################
86 1.1 christos # --- Main Program, DTrace ---
87 1.1 christos #
88 1.1 christos /usr/sbin/dtrace -n '
89 1.1 christos #pragma D option quiet
90 1.1 christos
91 1.1 christos inline string CLEAR = "'$clearstr'";
92 1.1 christos inline int OPT_read = '$opt_read';
93 1.1 christos inline int OPT_write = '$opt_write';
94 1.1 christos inline int PID = '$PID';
95 1.1 christos
96 1.1 christos unsigned long long totaltime;
97 1.1 christos unsigned long long totalbytes;
98 1.1 christos
99 1.1 christos enum runstate {
100 1.1 christos READ,
101 1.1 christos WRITE,
102 1.1 christos OTHER
103 1.1 christos };
104 1.1 christos
105 1.1 christos /* print header */
106 1.1 christos dtrace:::BEGIN
107 1.1 christos {
108 1.1 christos printf("Tracing ");
109 1.1 christos OPT_read && OPT_write ? printf("reads and writes") : 1;
110 1.1 christos OPT_read && ! OPT_write ? printf("reads") : 1;
111 1.1 christos ! OPT_read && OPT_write ? printf("writes") : 1;
112 1.1 christos printf("...");
113 1.1 christos totaltime = 0;
114 1.1 christos totalbytes = 0;
115 1.1 christos last = timestamp;
116 1.1 christos stamp = timestamp;
117 1.1 christos }
118 1.1 christos
119 1.1 christos /* sample reads */
120 1.1 christos syscall::read:entry,
121 1.1 christos syscall::pread*:entry
122 1.1 christos /pid == PID && OPT_read/
123 1.1 christos {
124 1.1 christos runstate = READ;
125 1.1 christos @logical["running", (uint64_t)0, ""] = sum(timestamp - last);
126 1.1 christos totaltime += timestamp - last;
127 1.1 christos last = timestamp;
128 1.1 christos
129 1.1 christos self->fd = arg0 + 1;
130 1.1 christos }
131 1.1 christos
132 1.1 christos fbt::fop_read:entry,
133 1.1 christos fbt::fop_write:entry
134 1.1 christos /self->fd/
135 1.1 christos {
136 1.1 christos self->path = args[0]->v_path == 0 ? "<none>" :
137 1.1 christos cleanpath(args[0]->v_path);
138 1.1 christos }
139 1.1 christos
140 1.1 christos syscall::read:return,
141 1.1 christos syscall::pread*:return
142 1.1 christos /pid == PID && OPT_read/
143 1.1 christos {
144 1.1 christos runstate = OTHER;
145 1.1 christos this->bytes = (int)arg0 > 0 ? (int)arg0 : 0;
146 1.1 christos @logical["read", self->fd - 1, self->path] = sum(timestamp - last);
147 1.1 christos @bytes["read", self->fd - 1, self->path] = sum(this->bytes);
148 1.1 christos totalbytes += this->bytes;
149 1.1 christos totaltime += timestamp - last;
150 1.1 christos last = timestamp;
151 1.1 christos self->path = 0;
152 1.1 christos self->fd = 0;
153 1.1 christos }
154 1.1 christos
155 1.1 christos
156 1.1 christos /* sample writes */
157 1.1 christos syscall::write:entry,
158 1.1 christos syscall::pwrite*:entry
159 1.1 christos /pid == PID && OPT_write/
160 1.1 christos {
161 1.1 christos runstate = WRITE;
162 1.1 christos @logical["running", (uint64_t)0, ""] = sum(timestamp - last);
163 1.1 christos totaltime += timestamp - last;
164 1.1 christos last = timestamp;
165 1.1 christos
166 1.1 christos self->fd = (int)arg0 + 1;
167 1.1 christos }
168 1.1 christos
169 1.1 christos syscall::write:return,
170 1.1 christos syscall::pwrite*:return
171 1.1 christos /pid == PID && OPT_write/
172 1.1 christos {
173 1.1 christos runstate = OTHER;
174 1.1 christos this->bytes = (int)arg0 > 0 ? (int)arg0 : 0;
175 1.1 christos @logical["write", self->fd - 1, self->path] = sum(timestamp - last);
176 1.1 christos @bytes["write", self->fd - 1, self->path] = sum(this->bytes);
177 1.1 christos totalbytes += this->bytes;
178 1.1 christos totaltime += timestamp - last;
179 1.1 christos last = timestamp;
180 1.1 christos self->path = 0;
181 1.1 christos self->fd = 0;
182 1.1 christos }
183 1.1 christos
184 1.1 christos sched:::on-cpu
185 1.1 christos /pid == PID/
186 1.1 christos {
187 1.1 christos @logical["waitcpu", (uint64_t)0, ""] = sum(timestamp - last);
188 1.1 christos totaltime += timestamp - last;
189 1.1 christos last = timestamp;
190 1.1 christos }
191 1.1 christos
192 1.1 christos
193 1.1 christos sched:::off-cpu
194 1.1 christos /pid == PID/
195 1.1 christos {
196 1.1 christos @logical["running", (uint64_t)0, ""] = sum(timestamp - last);
197 1.1 christos totaltime += timestamp - last;
198 1.1 christos last = timestamp;
199 1.1 christos }
200 1.1 christos
201 1.1 christos sched:::sleep
202 1.1 christos /pid == PID/
203 1.1 christos {
204 1.1 christos @logical["running", (uint64_t)0, ""] = sum(timestamp - last);
205 1.1 christos totaltime += timestamp - last;
206 1.1 christos last = timestamp;
207 1.1 christos }
208 1.1 christos
209 1.1 christos sched:::wakeup
210 1.1 christos /args[1]->pr_pid == PID && runstate == OTHER/
211 1.1 christos {
212 1.1 christos @logical["sleep", (uint64_t)0, ""] = sum(timestamp - last);
213 1.1 christos totaltime += timestamp - last;
214 1.1 christos last = timestamp;
215 1.1 christos }
216 1.1 christos
217 1.1 christos sched:::wakeup
218 1.1 christos /args[1]->pr_pid == PID && runstate == READ/
219 1.1 christos {
220 1.1 christos @logical["sleep-r", (uint64_t)0, ""] = sum(timestamp - last);
221 1.1 christos totaltime += timestamp - last;
222 1.1 christos last = timestamp;
223 1.1 christos }
224 1.1 christos
225 1.1 christos sched:::wakeup
226 1.1 christos /args[1]->pr_pid == PID && runstate == WRITE/
227 1.1 christos {
228 1.1 christos @logical["sleep-w", (uint64_t)0, ""] = sum(timestamp - last);
229 1.1 christos totaltime += timestamp - last;
230 1.1 christos last = timestamp;
231 1.1 christos }
232 1.1 christos
233 1.1 christos sched:::enqueue
234 1.1 christos /args[1]->pr_pid == PID/
235 1.1 christos {
236 1.1 christos @logical["waitcpu", (uint64_t)0, ""] = sum(timestamp - last);
237 1.1 christos totaltime += timestamp - last;
238 1.1 christos last = timestamp;
239 1.1 christos }
240 1.1 christos
241 1.1 christos sched:::dequeue
242 1.1 christos /args[1]->pr_pid == PID/
243 1.1 christos {
244 1.1 christos @logical["waitcpu", (uint64_t)0, ""] = sum(timestamp - last);
245 1.1 christos totaltime += timestamp - last;
246 1.1 christos last = timestamp;
247 1.1 christos }
248 1.1 christos
249 1.1 christos /* print report */
250 1.1 christos profile:::tick-5s
251 1.1 christos {
252 1.1 christos printf("%s", CLEAR);
253 1.1 christos normalize(@logical, totaltime / 100);
254 1.1 christos trunc(@logical, 10);
255 1.1 christos printf("%10s %7s %9s %-44s\n", "STATE", "FDNUM", "Time", "Filename");
256 1.1 christos printa("%10s %7d %@8d%% %-44.44s\n", @logical);
257 1.1 christos trunc(@logical);
258 1.1 christos
259 1.1 christos delta = timestamp - stamp;
260 1.1 christos stamp = timestamp;
261 1.1 christos normalize(@bytes, (1024 * delta) / 1000000000);
262 1.1 christos trunc(@bytes, 10);
263 1.1 christos printf("\n%10s %7s %9s %-44s\n", "STATE", "FDNUM", "KB/s",
264 1.1 christos "Filename");
265 1.1 christos printa("%10s %7d %@9d %-44.44s\n", @bytes);
266 1.1 christos trunc(@bytes);
267 1.1 christos
268 1.1 christos printf("\nTotal event time (ms): %d Total Mbytes/sec: %d\n",
269 1.1 christos totaltime / 1000000,
270 1.1 christos (totalbytes * 1000000000) / (delta * 1048576));
271 1.1 christos
272 1.1 christos totaltime = 0;
273 1.1 christos totalbytes = 0;
274 1.1 christos last = timestamp;
275 1.1 christos }
276 1.1 christos
277 1.1 christos dtrace:::END
278 1.1 christos {
279 1.1 christos trunc(@logical);
280 1.1 christos trunc(@bytes);
281 1.1 christos }
282 1.1 christos '
283