#!/usr/bin/sh # # dvmstat - vmstat by PID/name/command. # Written using DTrace (Solaris 10 3/05). # # This program provides vmstat like data for one particular PID, a # process name, or when running a command. It prints statistics # every second. # # 12-Jun-2005, ver 0.70 (first release. check for newer versions) # # USAGE: dvmstat { -p PID | -n name | command } # eg, # dvmstat -p 1871 # examine PID 1871 # dvmstat -n tar # examine processes called "tar" # dvmstat df -h # run and examine "df -h" # # FIELDS: # # re page reclaims Kb # maj major faults Kb # mf minor faults Kb # fr page frees Kb # epi executable page ins Kb # epo executable page outs Kb # api anonymous page ins Kb # apo anonymous page outs Kb # fpi filesystem page ins Kb # fpo filesystem page outs Kb # sy system calls number # # SEE ALSO: vmstat(1M) # # NOTES: # * When using dvmstat to run a command - if the command takes some time # to execute, dvmstat will print output every second. If the command runs # in less than a second, then the only one line of output will be printed. # # COPYRIGHT: Copyright (c) 2005 Brendan Gregg. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # (http://www.gnu.org/copyleft/gpl.html) # # Author: Brendan Gregg [Sydney, Australia] # # 12-Jun-2005 Brendan Gregg Created this. # #pragma D option quiet ############################## # --- Process Arguments --- # ### Default variables opt_pid=0; opt_name=0; pid=0; pname="."; opt_command=0; command="" ### Process options while getopts hn:p: name do case $name in p) opt_pid=1; pid=$OPTARG ;; n) opt_name=1; pname=$OPTARG ;; h|?) cat <<-END >&2 USAGE: dvmstat [-h] { -p PID | -n name | command } -p PID # examine this PID -n name # examine this process name eg, dvmstat -p 1871 # examine PID 1871 dvmstat -n tar # examine processes called "tar" dvmstat df -h # run and examine "df -h" END exit 1 esac done shift `expr $OPTIND - 1` ### Option logic if [ $opt_pid -eq 0 -a $opt_name -eq 0 ]; then opt_command=1 if [ "$*" = "" ]; then $0 -h exit fi command="$*" fi ################################# # --- Main Program, DTrace --- # dtrace=' #pragma D option quiet /* * Command line arguments */ inline int OPT_pid = '$opt_pid'; inline int OPT_name = '$opt_name'; inline int OPT_command = '$opt_command'; inline int PID = '$pid'; inline string NAME = "'$pname'"; inline string COMMAND = "'$command'"; inline int SCREEN = 21; /* * Initialise variables */ dtrace:::BEGIN { epi = 0; epo = 0; api = 0; apo = 0; fpi = 0; fpo = 0; re = 0; mf = 0; maj = 0; fr = 0; sy = 0; lines = SCREEN + 1; header = 0; } /* * Print header */ dtrace:::BEGIN, dtrace:::END, profile:::tick-1sec /(OPT_command && probename == "END") || (!(OPT_command && probename == "BEGIN") && lines++ > SCREEN)/ { printf("%6s %5s %5s %4s %4s %4s %4s %4s %4s %4s %6s\n", "re", "maj", "mf", "fr", "epi", "epo", "api", "apo", "fpi", "fpo", "sy"); lines = 0; } /* * Probe events * * this intentionally does not use an associative array for storing data, * for reasons of performance. */ vminfo:::execpgin /(OPT_pid && pid == PID) || (OPT_name && execname == NAME) || (OPT_command && pid == $target)/ { epi += arg0; } vminfo:::execpgout /(OPT_pid && pid == PID) || (OPT_name && execname == NAME) || (OPT_command && pid == $target)/ { epo += arg0; } vminfo:::anonpgin /(OPT_pid && pid == PID) || (OPT_name && execname == NAME) || (OPT_command && pid == $target)/ { api += arg0; } vminfo:::anonpgout /(OPT_pid && pid == PID) || (OPT_name && execname == NAME) || (OPT_command && pid == $target)/ { apo += arg0; } vminfo:::fspgin /(OPT_pid && pid == PID) || (OPT_name && execname == NAME) || (OPT_command && pid == $target)/ { fpi += arg0; } vminfo:::fspgout /(OPT_pid && pid == PID) || (OPT_name && execname == NAME) || (OPT_command && pid == $target)/ { fpo += arg0; } vminfo:::pgrec /(OPT_pid && pid == PID) || (OPT_name && execname == NAME) || (OPT_command && pid == $target)/ { re += arg0; } vminfo:::as_fault /(OPT_pid && pid == PID) || (OPT_name && execname == NAME) || (OPT_command && pid == $target)/ { mf += arg0; } vminfo:::maj_fault /(OPT_pid && pid == PID) || (OPT_name && execname == NAME) || (OPT_command && pid == $target)/ { maj += arg0; } vminfo:::dfree /(OPT_pid && pid == PID) || (OPT_name && execname == NAME) || (OPT_command && pid == $target)/ { fr += arg0; } syscall:::entry /(OPT_pid && pid == PID) || (OPT_name && execname == NAME) || (OPT_command && pid == $target)/ { sy++; } /* * Print output line */ profile:::tick-1sec, dtrace:::END { /* convert to kb */ re *= `pagesize / 1024; maj *= `pagesize / 1024; mf *= `pagesize / 1024; fr *= `pagesize / 1024; epi *= `pagesize / 1024; epo *= `pagesize / 1024; api *= `pagesize / 1024; apo *= `pagesize / 1024; fpi *= `pagesize / 1024; fpo *= `pagesize / 1024; /* print line */ printf("%6d %5d %5d %4d %4d %4d %4d %4d %4d %4d %6d\n", re, maj, mf, fr, epi, epo, api, apo, fpi, fpo, sy); /* clear counters */ epi = 0; epo = 0; api = 0; apo = 0; fpi = 0; fpo = 0; re = 0; mf = 0; maj = 0; fr = 0; sy = 0; } ' ### Run DTrace if [ $opt_command -eq 1 ]; then /usr/sbin/dtrace -n "$dtrace" -x evaltime=exec -c "$command" >&2 else /usr/sbin/dtrace -n "$dtrace" >&2 fi