]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - cddl/contrib/dtracetoolkit/Zones/zvmstat
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[FreeBSD/stable/10.git] / cddl / contrib / dtracetoolkit / Zones / zvmstat
1 #!/usr/bin/ksh
2 #
3 # zvmstat - print vmstat style info per Zone.
4 #           This uses DTrace (Solaris 10 3/05).
5 #
6 # This program must be run from the global zone as root.
7 #
8 # $Id: zvmstat 3 2007-08-01 10:50:08Z brendan $
9 #
10 # USAGE:        zvmstat [-ht] [interval [count]]
11 #
12 #               zvmstat         # default output
13 #                       -t      # print times
14 #  eg,
15 #               zvmstat 1       # print every 1 second
16 #               zvmstat 10 5    # print 5 x 10 second samples
17 #               zvmstat -t 5    # print every 5 seconds with time
18 #
19 #
20 # FIELDS:
21 #               re              page reclaims
22 #               mf              minor faults
23 #               fr              pages freed
24 #               sr              scan rate
25 #               epi             executable pages paged in
26 #               epo             executable pages paged out
27 #               epf             executable pages freed
28 #               api             anonymous pages paged in
29 #               apo             anonymous pages paged out
30 #               apf             anonymous pages freed
31 #               fpi             filesystem pages paged in
32 #               fpo             filesystem pages paged out
33 #               fpf             filesystem pages freed
34 #
35 # NOTES: 
36 # - Zone status should really be provided by Kstat, which currently
37 #   provides system wide values, per CPU and per processor set, but not per
38 #   zone. DTrace can fill this role in the meantime until Kstat supports zones.
39 # - First output does not contain summary since boot.
40 #
41 # SEE ALSO: prstat -Z
42 #
43 # COPYRIGHT: Copyright (c) 2005 Brendan Gregg.
44 #
45 # CDDL HEADER START
46 #
47 #  The contents of this file are subject to the terms of the
48 #  Common Development and Distribution License, Version 1.0 only
49 #  (the "License").  You may not use this file except in compliance
50 #  with the License.
51 #
52 #  You can obtain a copy of the license at Docs/cddl1.txt
53 #  or http://www.opensolaris.org/os/licensing.
54 #  See the License for the specific language governing permissions
55 #  and limitations under the License.
56 #
57 # CDDL HEADER END
58 #
59 # BUGS:
60 # - First output may not contain all zones due to how loops are achieved.
61 #   Check for newer versions.
62 #
63 # Author: Brendan Gregg  [Sydney, Australia]
64 #
65 # 11-May-2005   Brendan Gregg   Created this.
66 # 26-Jul-2005      "      "     Improved code.
67 # 08-Jan-2006      "      "     Last update.
68 #
69
70
71 ##############################
72 # --- Process Arguments ---
73 #
74
75 ### default variables
76 opt_time=0; interval=1; counts=1
77
78 ### process options
79 while getopts ht name
80 do
81         case $name in
82         t)      opt_time=1 ;;
83         h|?)    cat <<-END >&2
84                 USAGE: zvmstat [-ht] [interval [count]]
85                        zvmstat         # default output
86                                -t      # print times
87                    eg,
88                        zvmstat 1       # print every 1 second
89                        zvmstat 10 5    # print 5 x 10 second samples
90                        zvmstat -t 5    # print every 5 seconds with time
91                 END
92                 exit 1
93         esac
94 done
95 shift $(( OPTIND - 1 ))
96
97 ### option logic
98 if (( "0$1" > 0 )); then
99         interval=$1; counts=-1; shift
100 fi
101 if (( "0$1" > 0 )); then
102         counts=$1; shift
103 fi
104
105
106 #################################
107 # --- Main Program, DTrace ---
108 #
109 dtrace -n '
110  #pragma D option quiet
111  #pragma D option destructive
112  #pragma D option switchrate=10
113
114  /*
115   * Command line arguments
116   */
117  inline int OPT_time   = '$opt_time';
118  inline int INTERVAL   = '$interval';
119  inline int COUNTER    = '$counts';
120
121  /* 
122   * Initialise variables
123   */
124  dtrace:::BEGIN 
125  {
126         secs = INTERVAL; 
127         counts = COUNTER;
128         zonemax = 0;
129         listing = 1;
130         re[""] = 0; pi[""] = 0; po[""] = 0;
131         mf[""] = 0; sr[""] = 0; fr[""] = 0;
132         epi[""] = 0; epo[""] = 0; epf[""] = 0;
133         api[""] = 0; apo[""] = 0; apf[""] = 0;
134         fpi[""] = 0; fpo[""] = 0; fpf[""] = 0;
135  }
136
137  /*
138   * Build zonelist array
139   *
140   * Here we want the output of a command to be saved into an array
141   * inside dtrace. This is done by running the command, sending the
142   * output to /dev/null, and by probing its write syscalls from dtrace. 
143   *
144   * This is an example of a "scraper".
145   */
146
147  /*
148   * List zones
149   */
150  dtrace:::BEGIN 
151  {
152         /* run zoneadm */
153         system("/usr/sbin/zoneadm list > /dev/null; echo END > /dev/null");
154  }
155
156  /*
157   * Scrape zone listing
158   */
159  syscall::write:entry
160  /listing && (execname == "zoneadm") && 
161  (curthread->t_procp->p_parent->p_ppid == $pid)/
162  {
163         /* read zoneadm output */
164         zonelist[zonemax] = stringof(copyin(arg1, arg2 - 1));
165
166         /* increment max number of zones */
167         zonemax++;
168  }
169
170  /*
171   * Finish scraping zones
172   */
173  syscall::write:entry
174  /listing && (execname == "sh") && (ppid == $pid)/
175  {
176         /*
177          * this end tag lets us know our zonelist has finished.
178          * thanks A. Packer.
179          */
180         listing = stringof(copyin(arg1, arg2 - 1)) == "END" ? 0 : 1;
181  }
182
183  /*
184   * Record vminfo counters
185   */
186  vminfo:::pgrec      { re[zonename] += arg0; }
187  vminfo:::as_fault   { mf[zonename] += arg0; }
188  vminfo:::scan       { sr[zonename] += arg0; }
189  vminfo:::execpgin   { epi[zonename] += arg0; }
190  vminfo:::execpgout  { epo[zonename] += arg0; }
191  vminfo:::execfree   { epf[zonename] += arg0; fr[zonename] += arg0; }
192  vminfo:::anonpgin   { api[zonename] += arg0; }
193  vminfo:::anonpgout  { apo[zonename] += arg0; }
194  vminfo:::anonfree   { apf[zonename] += arg0; fr[zonename] += arg0; }
195  vminfo:::fspgin     { fpi[zonename] += arg0; }
196  vminfo:::fspgout    { fpo[zonename] += arg0; }
197  vminfo:::fsfree     { fpf[zonename] += arg0; fr[zonename] += arg0; }
198
199  /*
200   * Timer
201   */
202  profile:::tick-1sec
203  {
204         secs--;
205  }
206
207  /*
208   * Check for exit
209   */
210  profile:::tick-1sec
211  /counts == 0/
212  {
213         exit(0);
214  }
215
216  /*
217   * Print header line
218   */
219  profile:::tick-1sec
220  /secs == 0/
221  {
222         /* set counters */
223         secs = INTERVAL;
224         counts--;
225         zonei = 0;
226
227         /* print time */
228         OPT_time ? printf("\n%Y,\n",walltimestamp) : 1;
229
230         /* print output line */
231         printf("%10s %4s %5s %4s %5s %4s %4s %4s %4s %4s %4s %4s %4s %4s\n",
232             "ZONE", "re", "mf", "fr", "sr", "epi", "epo", "epf", "api", "apo",
233             "apf", "fpi", "fpo", "fpf");
234
235         /* ensure zone writes are triggered */
236         printf(" \b");
237  }
238
239  /*
240   * Print zone status line
241   *
242   * This is a fairly interesting function in that it loops over the keys in 
243   * an associative array and prints out the values. DTrace cant really do 
244   * loops, and generally doesnt need to. We "cheat" by generating writes
245   * in the above probe which in turn trigger the probe below which 
246   * contains the contents of each loop. Dont do this at home! We are
247   * supposed to use aggreagations instead, wherever possible.
248   *
249   * This is an example of a "feedback loop".
250   */
251  syscall::write:return
252  /pid == $pid && zonei < zonemax/
253  {
254         /* fetch zonename */
255         self->zone = zonelist[zonei];
256
257         /* print output */
258         printf("%10s %4d %5d %4d %5d %4d %4d %4d %4d %4d %4d %4d %4d %4d\n",
259             self->zone, re[self->zone], mf[self->zone], fr[self->zone],
260             sr[self->zone], epi[self->zone], epo[self->zone],
261             epf[self->zone], api[self->zone], apo[self->zone],
262             apf[self->zone], fpi[self->zone], fpo[self->zone],
263             fpf[self->zone]);
264         
265         /* clear values */
266         re[self->zone] = 0; mf[self->zone] = 0; fr[self->zone] = 0;
267         sr[self->zone] = 0; epi[self->zone] = 0; epo[self->zone] = 0;
268         epf[self->zone] = 0; api[self->zone] = 0; apo[self->zone] = 0;
269         apf[self->zone] = 0; fpi[self->zone] = 0; fpo[self->zone] = 0;
270         fpf[self->zone] = 0;
271         self->zone = 0;
272         
273         /* go to next zone */
274         zonei++;
275  }
276 '
277