diff options
Diffstat (limited to 'cddl/contrib/dtracetoolkit/Proc/pfilestat')
-rwxr-xr-x | cddl/contrib/dtracetoolkit/Proc/pfilestat | 282 |
1 files changed, 282 insertions, 0 deletions
diff --git a/cddl/contrib/dtracetoolkit/Proc/pfilestat b/cddl/contrib/dtracetoolkit/Proc/pfilestat new file mode 100755 index 0000000..c6aaba3 --- /dev/null +++ b/cddl/contrib/dtracetoolkit/Proc/pfilestat @@ -0,0 +1,282 @@ +#!/usr/bin/sh +# +# pfilestat +# +# This prints I/O statistics for each file descriptor within a process. +# In particular, the time break down during read() and write() events is +# measured. +# +# $Id: pfilestat 4 2007-08-01 11:01:38Z brendan $ +# +# USAGE: pfilestat [-r|-w] pid +# +# FIELDS: +# STATE microstate: running, sleeping, waitcpu, read, write +# FDUM File Descriptor ID +# Time Percentage of wallclock time in each STATE +# File Name of file, if known +# +# COPYRIGHT: Copyright (c) 2006 Richard McDougall. +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at Docs/cddl1.txt +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# CDDL HEADER END +# +# ToDo: +# Trace readv() and writev(). +# +# 20-Feb-2006 Richard McDougall created this. +# 24-Feb-2006 Brendan Gregg tweaked code. +# 20-Mar-2006 " " tweaked code. +# 20-Mar-2006 " " last update. + + +############################## +# --- Process Arguments --- +# + +### Default variables +opt_read=0; opt_write=0 + +### Process options +while getopts hrw name +do + case $name in + r) opt_read=1 ;; + w) opt_write=1 ;; + h|?) cat <<-END >&2 + USAGE: pfilestat [-r|-w] pid + -r # reads only + -w # writes only + eg, + pfilestat pid # default, r+w counts + pfilestat -r pid # read count only + END + exit 1 + esac +done +shift `expr $OPTIND - 1` + +PID=$1 +clearstr=`clear` + +if [ -z "$PID" ] +then + echo "Must supply pid" + exit 1 +fi + +### Option logic +if [ $opt_read -eq 0 -a $opt_write -eq 0 ]; then + opt_read=1; opt_write=1 +fi + + +################################# +# --- Main Program, DTrace --- +# +/usr/sbin/dtrace -n ' + #pragma D option quiet + + inline string CLEAR = "'$clearstr'"; + inline int OPT_read = '$opt_read'; + inline int OPT_write = '$opt_write'; + inline int PID = '$PID'; + + unsigned long long totaltime; + unsigned long long totalbytes; + + enum runstate { + READ, + WRITE, + OTHER + }; + + /* print header */ + dtrace:::BEGIN + { + printf("Tracing "); + OPT_read && OPT_write ? printf("reads and writes") : 1; + OPT_read && ! OPT_write ? printf("reads") : 1; + ! OPT_read && OPT_write ? printf("writes") : 1; + printf("..."); + totaltime = 0; + totalbytes = 0; + last = timestamp; + stamp = timestamp; + } + + /* sample reads */ + syscall::read:entry, + syscall::pread*:entry + /pid == PID && OPT_read/ + { + runstate = READ; + @logical["running", (uint64_t)0, ""] = sum(timestamp - last); + totaltime += timestamp - last; + last = timestamp; + + self->fd = arg0 + 1; + } + + fbt::fop_read:entry, + fbt::fop_write:entry + /self->fd/ + { + self->path = args[0]->v_path == 0 ? "<none>" : + cleanpath(args[0]->v_path); + } + + syscall::read:return, + syscall::pread*:return + /pid == PID && OPT_read/ + { + runstate = OTHER; + this->bytes = (int)arg0 > 0 ? (int)arg0 : 0; + @logical["read", self->fd - 1, self->path] = sum(timestamp - last); + @bytes["read", self->fd - 1, self->path] = sum(this->bytes); + totalbytes += this->bytes; + totaltime += timestamp - last; + last = timestamp; + self->path = 0; + self->fd = 0; + } + + + /* sample writes */ + syscall::write:entry, + syscall::pwrite*:entry + /pid == PID && OPT_write/ + { + runstate = WRITE; + @logical["running", (uint64_t)0, ""] = sum(timestamp - last); + totaltime += timestamp - last; + last = timestamp; + + self->fd = (int)arg0 + 1; + } + + syscall::write:return, + syscall::pwrite*:return + /pid == PID && OPT_write/ + { + runstate = OTHER; + this->bytes = (int)arg0 > 0 ? (int)arg0 : 0; + @logical["write", self->fd - 1, self->path] = sum(timestamp - last); + @bytes["write", self->fd - 1, self->path] = sum(this->bytes); + totalbytes += this->bytes; + totaltime += timestamp - last; + last = timestamp; + self->path = 0; + self->fd = 0; + } + + sched:::on-cpu + /pid == PID/ + { + @logical["waitcpu", (uint64_t)0, ""] = sum(timestamp - last); + totaltime += timestamp - last; + last = timestamp; + } + + + sched:::off-cpu + /pid == PID/ + { + @logical["running", (uint64_t)0, ""] = sum(timestamp - last); + totaltime += timestamp - last; + last = timestamp; + } + + sched:::sleep + /pid == PID/ + { + @logical["running", (uint64_t)0, ""] = sum(timestamp - last); + totaltime += timestamp - last; + last = timestamp; + } + + sched:::wakeup + /args[1]->pr_pid == PID && runstate == OTHER/ + { + @logical["sleep", (uint64_t)0, ""] = sum(timestamp - last); + totaltime += timestamp - last; + last = timestamp; + } + + sched:::wakeup + /args[1]->pr_pid == PID && runstate == READ/ + { + @logical["sleep-r", (uint64_t)0, ""] = sum(timestamp - last); + totaltime += timestamp - last; + last = timestamp; + } + + sched:::wakeup + /args[1]->pr_pid == PID && runstate == WRITE/ + { + @logical["sleep-w", (uint64_t)0, ""] = sum(timestamp - last); + totaltime += timestamp - last; + last = timestamp; + } + + sched:::enqueue + /args[1]->pr_pid == PID/ + { + @logical["waitcpu", (uint64_t)0, ""] = sum(timestamp - last); + totaltime += timestamp - last; + last = timestamp; + } + + sched:::dequeue + /args[1]->pr_pid == PID/ + { + @logical["waitcpu", (uint64_t)0, ""] = sum(timestamp - last); + totaltime += timestamp - last; + last = timestamp; + } + + /* print report */ + profile:::tick-5s + { + printf("%s", CLEAR); + normalize(@logical, totaltime / 100); + trunc(@logical, 10); + printf("%10s %7s %9s %-44s\n", "STATE", "FDNUM", "Time", "Filename"); + printa("%10s %7d %@8d%% %-44.44s\n", @logical); + trunc(@logical); + + delta = timestamp - stamp; + stamp = timestamp; + normalize(@bytes, (1024 * delta) / 1000000000); + trunc(@bytes, 10); + printf("\n%10s %7s %9s %-44s\n", "STATE", "FDNUM", "KB/s", + "Filename"); + printa("%10s %7d %@9d %-44.44s\n", @bytes); + trunc(@bytes); + + printf("\nTotal event time (ms): %d Total Mbytes/sec: %d\n", + totaltime / 1000000, + (totalbytes * 1000000000) / (delta * 1048576)); + + totaltime = 0; + totalbytes = 0; + last = timestamp; + } + + dtrace:::END + { + trunc(@logical); + trunc(@bytes); + } +' |