]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - cddl/contrib/dtracetoolkit/rwtop
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[FreeBSD/stable/10.git] / cddl / contrib / dtracetoolkit / rwtop
1 #!/usr/bin/ksh
2 #
3 # rwtop - display top read/write bytes by process.
4 #         Written using DTrace (Solaris 10 3/05).
5 #
6 # This is measuring reads and writes at the application level. This matches
7 # read and write system calls.
8 #
9 # $Id: rwtop 3 2007-08-01 10:50:08Z brendan $
10 #
11 # USAGE:        rwtop [-cC] [-j|-Z] [-n name] [-p pid]
12 #                     [-t top] [interval [count]]
13
14 #               rwtop           # default output, 5 second samples
15 #
16 #               -C              # don't clear the screen
17 #               -c              # print counts
18 #               -j              # print project ID
19 #               -Z              # print zone ID
20 #               -n name         # this process name only
21 #               -p PID          # this PID only
22 #               -t top          # print top number only
23 #       eg,
24 #               rwtop 1         # 1 second samples
25 #               rwtop -t 10     # print top 10 only
26 #               rwtop -n bash   # monitor processes named "bash"
27 #               rwtop -C 5 12   # print 12 x 5 second samples
28 #
29 # FIELDS:
30 #               ZONE            Zone ID
31 #               PROJ            Project ID
32 #               UID             User ID
33 #               PID             Process ID
34 #               PPID            Parent Process ID
35 #               CMD             Process name
36 #               D               Direction, Read or Write
37 #               BYTES           Total bytes during sample
38 #               app_r           total reads during sample, Kbytes
39 #               app_w           total writes during sample, Kbytes
40 #
41 # SEE ALSO:     iotop
42 #
43 # INSPIRATION:  top(1) by William LeFebvre
44 #
45 # COPYRIGHT: Copyright (c) 2005, 2006 Brendan Gregg.
46 #
47 # CDDL HEADER START
48 #
49 #  The contents of this file are subject to the terms of the
50 #  Common Development and Distribution License, Version 1.0 only
51 #  (the "License").  You may not use this file except in compliance
52 #  with the License.
53 #
54 #  You can obtain a copy of the license at Docs/cddl1.txt
55 #  or http://www.opensolaris.org/os/licensing.
56 #  See the License for the specific language governing permissions
57 #  and limitations under the License.
58 #
59 # CDDL HEADER END
60 #
61 # Author: Brendan Gregg  [Sydney, Australia]
62 #
63 # 24-Jul-2005   Brendan Gregg   Created this.
64 # 20-Apr-2006      "      "     Last update.
65
66
67 ##############################
68 # --- Process Arguments ---
69 #
70
71 ### default variables
72 opt_name=0; opt_pid=0; opt_clear=1; opt_proj=0; opt_zone=0
73 opt_def=1; opt_bytes=1; filter=0; pname=.; pid=0
74 opt_top=0; opt_count=0; interval=5; count=-1; top=0
75
76 ### process options
77 while getopts Cchn:p:jt:Z name
78 do
79         case $name in
80         C)      opt_clear=0 ;;
81         c)      opt_count=1; opt_bytes=0 ;;
82         n)      opt_name=1; pname=$OPTARG ;;
83         p)      opt_pid=1; pid=$OPTARG ;;
84         j)      opt_proj=1; opt_def=0 ;;
85         t)      opt_top=1; top=$OPTARG ;;
86         Z)      opt_zone=1; opt_def=0 ;;
87         h|?)    cat <<-END >&2
88                 USAGE: rwtop [-cC] [-j|-Z] [-n name] [-p pid]
89                              [-t top] [interval [count]]
90  
91                                 -C        # don't clear the screen
92                                 -c        # print counts
93                                 -j        # print project ID
94                                 -Z        # print zone ID
95                                 -n name   # this process name only
96                                 -p PID    # this PID only
97                                 -t top    # print top number only
98                    eg,
99                         rwtop          # default output, 5 second samples
100                         rwtop 1        # 1 second samples
101                         rwtop -t 10    # print top 10 only
102                         rwtop -n bash  # monitor processes named "bash"
103                         rwtop -C 5 12  # print 12 x 5 second samples
104                 END
105                 exit 1
106         esac
107 done
108
109 shift $(( $OPTIND - 1 ))
110
111 ### option logic
112 if [[ "$1" > 0 ]]; then
113         interval=$1; shift
114 fi
115 if [[ "$1" > 0 ]]; then
116         count=$1; shift
117 fi
118 if (( opt_proj && opt_zone )); then
119         opt_proj=0
120 fi
121 if (( opt_name || opt_pid )); then
122         filter=1
123 fi
124 if (( opt_clear )); then
125         clearstr=`clear`
126 else
127         clearstr=.
128 fi
129
130
131
132 #################################
133 # --- Main Program, DTrace ---
134 #
135 /usr/sbin/dtrace -n '
136  /*
137   * Command line arguments
138   */
139  inline int OPT_def     = '$opt_def';
140  inline int OPT_proj    = '$opt_proj';
141  inline int OPT_zone    = '$opt_zone';
142  inline int OPT_clear   = '$opt_clear';
143  inline int OPT_bytes   = '$opt_bytes';
144  inline int OPT_count   = '$opt_count';
145  inline int OPT_name    = '$opt_name';
146  inline int OPT_pid     = '$opt_pid';
147  inline int OPT_top     = '$opt_top';
148  inline int INTERVAL    = '$interval';
149  inline int COUNTER     = '$count';
150  inline int FILTER      = '$filter';
151  inline int TOP         = '$top';
152  inline int PID         = '$pid';
153  inline string NAME     = "'$pname'";
154  inline string CLEAR    = "'$clearstr'";
155  
156  #pragma D option quiet
157
158  /*
159   * Print header
160   */
161  dtrace:::BEGIN 
162  {
163         /* starting values */
164         counts = COUNTER;
165         secs = INTERVAL;
166         app_r = 0;
167         app_w = 0;
168
169         printf("Tracing... Please wait.\n");
170  }
171
172  /*
173   * Check event is being traced
174   */
175  sysinfo:::readch,
176  sysinfo:::writech
177  /pid != $pid/
178  { 
179         /* default is to trace unless filtering, */
180         this->ok = FILTER ? 0 : 1;
181
182         /* check each filter, */
183         (OPT_name == 1 && NAME == execname)? this->ok = 1 : 1;
184         (OPT_pid == 1 && PID == pid) ? this->ok = 1 : 1;
185  }
186
187  /*
188   * Increment tallys
189   */
190  sysinfo:::readch
191  /this->ok/
192  {
193         app_r += arg0;
194  }
195  sysinfo:::writech
196  /this->ok/
197  {
198         app_w += arg0;
199  }
200
201  /*
202   * Process event
203   */
204  sysinfo:::readch,
205  sysinfo:::writech
206  /this->ok/
207  {
208         /* choose statistic to track */
209         this->value = OPT_bytes ? arg0 : 1;
210         
211         /*
212          * Save details
213          */
214         OPT_def ? @out[uid, pid, ppid, execname,
215             probename == "readch" ? "R" : "W"] = sum(this->value) : 1;
216         OPT_proj ? @out[curpsinfo->pr_projid, pid, ppid, execname,
217             probename == "readch" ? "R" : "W"] = sum(this->value) : 1;
218         OPT_zone ? @out[curpsinfo->pr_zoneid, pid, ppid, execname,
219             probename == "readch" ? "R" : "W"] = sum(this->value) : 1;
220
221         this->ok = 0;
222  }
223
224  /*
225   * Timer
226   */
227  profile:::tick-1sec
228  {
229         secs--;
230  }
231
232  /*
233   * Print Report
234   */
235  profile:::tick-1sec
236  /secs == 0/
237  {
238         /* fetch 1 min load average */
239         this->load1a  = `hp_avenrun[0] / 65536;
240         this->load1b  = ((`hp_avenrun[0] % 65536) * 100) / 65536;
241
242         /* convert counters to Kbytes */
243         app_r /= 1024;
244         app_w /= 1024;
245
246         /* print status */
247         OPT_clear ? printf("%s", CLEAR) : 1;
248         printf("%Y,  load: %d.%02d,  app_r: %6d KB,  app_w: %6d KB\n\n",
249             walltimestamp, this->load1a, this->load1b, app_r, app_w);
250
251         /* print headers */
252         OPT_def  ? printf("  UID ") : 1;
253         OPT_proj ? printf(" PROJ ") : 1;
254         OPT_zone ? printf(" ZONE ") : 1;
255         printf("%6s %6s %-16s %1s",
256             "PID", "PPID", "CMD", "D");
257         OPT_bytes ? printf(" %16s\n", "BYTES") : 1;
258         OPT_count ? printf(" %16s\n", "COUNT") : 1;
259
260         /* truncate to top lines if needed */
261         OPT_top ? trunc(@out, TOP) : 1;
262
263         /* print data */
264         printa("%5d %6d %6d %-16s %1s %16@d\n", @out);
265         printf("\n");
266
267         /* clear data */
268         trunc(@out);
269         app_r = 0;
270         app_w = 0;
271         secs = INTERVAL;
272         counts--;
273  }
274
275  /*
276   * End of program
277   */
278  profile:::tick-1sec
279  /counts == 0/
280  {
281         exit(0);
282  }
283
284  /*
285   * Cleanup for Ctrl-C
286   */
287  dtrace:::END
288  {
289         trunc(@out);
290  }
291 '
292