1235368Sgnn#!/usr/bin/sh
2235368Sgnn#
3235368Sgnn# dvmstat - vmstat by PID/name/command.
4235368Sgnn#           Written using DTrace (Solaris 10 3/05).
5235368Sgnn#
6235368Sgnn# This program provides vmstat like data for one particular PID, a 
7235368Sgnn# process name, or when running a command. It prints statistics
8235368Sgnn# every second.
9235368Sgnn#
10235368Sgnn# $Id: dvmstat 3 2007-08-01 10:50:08Z brendan $
11235368Sgnn#
12235368Sgnn# USAGE:	dvmstat { -p PID | -n name | command }
13235368Sgnn#  eg,
14235368Sgnn#		dvmstat -p 1871       # examine PID 1871
15235368Sgnn#		dvmstat -n tar        # examine processes called "tar"
16235368Sgnn#		dvmstat df -h         # run and examine "df -h"
17235368Sgnn#
18235368Sgnn# FIELDS: 
19235368Sgnn#		re	page reclaims		Kbytes
20235368Sgnn#		maj	major faults		Kbytes
21235368Sgnn#		mf	minor faults		Kbytes
22235368Sgnn#		fr	page frees		Kbytes
23235368Sgnn#		epi	executable page ins	Kbytes
24235368Sgnn#		epo	executable page out	Kbytes
25235368Sgnn#		api	anonymous page ins	Kbytes
26235368Sgnn#		apo	anonymous page outs	Kbytes
27235368Sgnn#		fpi	filesystem page ins	Kbytes
28235368Sgnn#		fpo	filesystem page outs	Kbytes
29235368Sgnn#		sy	system calls		number
30235368Sgnn#
31235368Sgnn# SEE ALSO:	vmstat(1M)
32235368Sgnn#
33235368Sgnn# NOTES:
34235368Sgnn#
35235368Sgnn# When using dvmstat to run a command - if the command takes some time
36235368Sgnn# to execute, dvmstat will print output every second. If the command runs
37235368Sgnn# in less than a second, then the only one line of output will be printed.
38235368Sgnn#
39235368Sgnn# COPYRIGHT: Copyright (c) 2005 Brendan Gregg.
40235368Sgnn#
41235368Sgnn# CDDL HEADER START
42235368Sgnn#
43235368Sgnn#  The contents of this file are subject to the terms of the
44235368Sgnn#  Common Development and Distribution License, Version 1.0 only
45235368Sgnn#  (the "License").  You may not use this file except in compliance
46235368Sgnn#  with the License.
47235368Sgnn#
48235368Sgnn#  You can obtain a copy of the license at Docs/cddl1.txt
49235368Sgnn#  or http://www.opensolaris.org/os/licensing.
50235368Sgnn#  See the License for the specific language governing permissions
51235368Sgnn#  and limitations under the License.
52235368Sgnn#
53235368Sgnn# CDDL HEADER END
54235368Sgnn#
55235368Sgnn# Author: Brendan Gregg  [Sydney, Australia]
56235368Sgnn#
57235368Sgnn# 12-Jun-2005	Brendan Gregg	Created this.
58235368Sgnn# 08-Jan-2006	   "      "	Last update.
59235368Sgnn# 
60235368Sgnn
61235368Sgnn##############################
62235368Sgnn# --- Process Arguments ---
63235368Sgnn#
64235368Sgnn
65235368Sgnn### Default variables
66235368Sgnnopt_pid=0; opt_name=0; pid=0; pname="."; opt_command=0; command=""
67235368Sgnn
68235368Sgnn### Process options
69235368Sgnnwhile getopts hn:p: name
70235368Sgnndo
71235368Sgnn        case $name in
72235368Sgnn        p)      opt_pid=1; pid=$OPTARG ;;
73235368Sgnn        n)      opt_name=1; pname=$OPTARG ;;
74235368Sgnn        h|?)    cat <<-END >&2
75235368Sgnn		USAGE: dvmstat [-h] { -p PID | -n name | command }
76235368Sgnn		           -p PID          # examine this PID
77235368Sgnn		           -n name         # examine this process name
78235368Sgnn		  eg,
79235368Sgnn		       dvmstat -p 1871     # examine PID 1871
80235368Sgnn		       dvmstat -n tar      # examine processes called "tar"
81235368Sgnn		       dvmstat df -h       # run and examine "df -h"
82235368Sgnn		END
83235368Sgnn                exit 1
84235368Sgnn        esac
85235368Sgnndone
86235368Sgnnshift `expr $OPTIND - 1`
87235368Sgnn
88235368Sgnn
89235368Sgnn### Option logic
90235368Sgnnif [ $opt_pid -eq 0 -a $opt_name -eq 0 ]; then
91235368Sgnn        opt_command=1
92235368Sgnn        if [ "$*" = "" ]; then
93235368Sgnn                $0 -h
94235368Sgnn                exit
95235368Sgnn        fi
96235368Sgnn        command="$*"
97235368Sgnnfi
98235368Sgnn
99235368Sgnn
100235368Sgnn#################################
101235368Sgnn# --- Main Program, DTrace ---
102235368Sgnn#
103235368Sgnndtrace='
104235368Sgnn #pragma D option quiet
105235368Sgnn
106235368Sgnn /*
107235368Sgnn  * Command line arguments
108235368Sgnn  */
109235368Sgnn inline int OPT_pid      = '$opt_pid';
110235368Sgnn inline int OPT_name     = '$opt_name';
111235368Sgnn inline int OPT_command  = '$opt_command';
112235368Sgnn inline int PID          = '$pid';
113235368Sgnn inline string NAME      = "'$pname'";
114235368Sgnn inline string COMMAND   = "'$command'";
115235368Sgnn inline int SCREEN       = 21;
116235368Sgnn
117235368Sgnn /*
118235368Sgnn  * Initialise variables
119235368Sgnn  */
120235368Sgnn dtrace:::BEGIN
121235368Sgnn {
122235368Sgnn	epi = 0; epo = 0; api = 0; apo = 0; fpi = 0; fpo = 0;
123235368Sgnn	re = 0; mf = 0; maj = 0; fr = 0; sy = 0;
124235368Sgnn	lines = SCREEN + 1;
125235368Sgnn	header = 0;
126235368Sgnn }
127235368Sgnn
128235368Sgnn /*
129235368Sgnn  * Print header
130235368Sgnn  */
131235368Sgnn dtrace:::BEGIN,
132235368Sgnn dtrace:::END,
133235368Sgnn profile:::tick-1sec
134235368Sgnn /(OPT_command && probename == "END") || 
135235368Sgnn  (!(OPT_command && probename == "BEGIN") && lines++ > SCREEN)/
136235368Sgnn {
137235368Sgnn	printf("%6s %5s %5s %4s %4s %4s %4s %4s %4s %4s %6s\n",
138235368Sgnn	    "re", "maj", "mf", "fr", "epi", "epo", "api", "apo", 
139235368Sgnn	    "fpi", "fpo", "sy");
140235368Sgnn	lines = 0;
141235368Sgnn }
142235368Sgnn
143235368Sgnn /*
144235368Sgnn  * Probe events
145235368Sgnn  *
146235368Sgnn  * this intentionally does not use an associative array for storing data,
147235368Sgnn  * for reasons of performance.
148235368Sgnn  */
149235368Sgnn
150235368Sgnn vminfo:::execpgin
151235368Sgnn /(OPT_pid && pid == PID) ||
152235368Sgnn  (OPT_name && execname == NAME) ||
153235368Sgnn  (OPT_command && pid == $target)/
154235368Sgnn { epi += arg0; }
155235368Sgnn
156235368Sgnn vminfo:::execpgout
157235368Sgnn /(OPT_pid && pid == PID) ||
158235368Sgnn  (OPT_name && execname == NAME) ||
159235368Sgnn  (OPT_command && pid == $target)/
160235368Sgnn { epo += arg0; }
161235368Sgnn
162235368Sgnn vminfo:::anonpgin
163235368Sgnn /(OPT_pid && pid == PID) ||
164235368Sgnn  (OPT_name && execname == NAME) ||
165235368Sgnn  (OPT_command && pid == $target)/
166235368Sgnn { api += arg0; }
167235368Sgnn
168235368Sgnn vminfo:::anonpgout
169235368Sgnn /(OPT_pid && pid == PID) ||
170235368Sgnn  (OPT_name && execname == NAME) ||
171235368Sgnn  (OPT_command && pid == $target)/
172235368Sgnn { apo += arg0; }
173235368Sgnn
174235368Sgnn vminfo:::fspgin
175235368Sgnn /(OPT_pid && pid == PID) ||
176235368Sgnn  (OPT_name && execname == NAME) ||
177235368Sgnn  (OPT_command && pid == $target)/
178235368Sgnn { fpi += arg0; }
179235368Sgnn
180235368Sgnn vminfo:::fspgout
181235368Sgnn /(OPT_pid && pid == PID) ||
182235368Sgnn  (OPT_name && execname == NAME) ||
183235368Sgnn  (OPT_command && pid == $target)/
184235368Sgnn { fpo += arg0; }
185235368Sgnn
186235368Sgnn vminfo:::pgrec
187235368Sgnn /(OPT_pid && pid == PID) ||
188235368Sgnn  (OPT_name && execname == NAME) ||
189235368Sgnn  (OPT_command && pid == $target)/
190235368Sgnn { re += arg0; }
191235368Sgnn
192235368Sgnn vminfo:::as_fault
193235368Sgnn /(OPT_pid && pid == PID) ||
194235368Sgnn  (OPT_name && execname == NAME) ||
195235368Sgnn  (OPT_command && pid == $target)/
196235368Sgnn { mf += arg0; }
197235368Sgnn
198235368Sgnn vminfo:::maj_fault
199235368Sgnn /(OPT_pid && pid == PID) ||
200235368Sgnn  (OPT_name && execname == NAME) ||
201235368Sgnn  (OPT_command && pid == $target)/
202235368Sgnn { maj += arg0; }
203235368Sgnn
204235368Sgnn vminfo:::dfree
205235368Sgnn /(OPT_pid && pid == PID) ||
206235368Sgnn  (OPT_name && execname == NAME) ||
207235368Sgnn  (OPT_command && pid == $target)/
208235368Sgnn { fr += arg0; }
209235368Sgnn
210235368Sgnn syscall:::entry
211235368Sgnn /(OPT_pid && pid == PID) ||
212235368Sgnn  (OPT_name && execname == NAME) ||
213235368Sgnn  (OPT_command && pid == $target)/
214235368Sgnn { sy++; }
215235368Sgnn
216235368Sgnn /* 
217235368Sgnn  * Print output line
218235368Sgnn  */
219235368Sgnn profile:::tick-1sec,
220235368Sgnn dtrace:::END
221235368Sgnn {
222235368Sgnn	/* convert to Kbytes */
223235368Sgnn	re  *= `_pagesize / 1024;
224235368Sgnn	maj *= `_pagesize / 1024;
225235368Sgnn	mf  *= `_pagesize / 1024;
226235368Sgnn	fr  *= `_pagesize / 1024;
227235368Sgnn	epi *= `_pagesize / 1024;
228235368Sgnn	epo *= `_pagesize / 1024;
229235368Sgnn	api *= `_pagesize / 1024;
230235368Sgnn	apo *= `_pagesize / 1024;
231235368Sgnn	fpi *= `_pagesize / 1024;
232235368Sgnn	fpo *= `_pagesize / 1024;
233235368Sgnn
234235368Sgnn	/* print line */
235235368Sgnn	printf("%6d %5d %5d %4d %4d %4d %4d %4d %4d %4d %6d\n",
236235368Sgnn	    re, maj, mf, fr, epi, epo, api, apo, fpi, fpo, sy);
237235368Sgnn
238235368Sgnn	/* clear counters */
239235368Sgnn	epi = 0; epo = 0; api = 0; apo = 0; fpi = 0; fpo = 0;
240235368Sgnn	re = 0; mf = 0; maj = 0; fr = 0; sy = 0;
241235368Sgnn }
242235368Sgnn'
243235368Sgnn
244235368Sgnn### Run DTrace
245235368Sgnnif [ $opt_command -eq 1 ]; then
246235368Sgnn        /usr/sbin/dtrace -n "$dtrace" -x evaltime=exec -c "$command" >&2
247235368Sgnnelse
248235368Sgnn        /usr/sbin/dtrace -n "$dtrace" >&2
249235368Sgnnfi
250235368Sgnn
251