1 1.1 christos #!/usr/bin/sh 2 1.1 christos # 3 1.1 christos # pfilestat 4 1.1 christos # 5 1.1 christos # This prints I/O statistics for each file descriptor within a process. 6 1.1 christos # In particular, the time break down during read() and write() events is 7 1.1 christos # measured. 8 1.1 christos # 9 1.1 christos # $Id: pfilestat,v 1.1.1.1 2015/09/30 22:01:09 christos Exp $ 10 1.1 christos # 11 1.1 christos # USAGE: pfilestat [-r|-w] pid 12 1.1 christos # 13 1.1 christos # FIELDS: 14 1.1 christos # STATE microstate: running, sleeping, waitcpu, read, write 15 1.1 christos # FDUM File Descriptor ID 16 1.1 christos # Time Percentage of wallclock time in each STATE 17 1.1 christos # File Name of file, if known 18 1.1 christos # 19 1.1 christos # COPYRIGHT: Copyright (c) 2006 Richard McDougall. 20 1.1 christos # 21 1.1 christos # CDDL HEADER START 22 1.1 christos # 23 1.1 christos # The contents of this file are subject to the terms of the 24 1.1 christos # Common Development and Distribution License, Version 1.0 only 25 1.1 christos # (the "License"). You may not use this file except in compliance 26 1.1 christos # with the License. 27 1.1 christos # 28 1.1 christos # You can obtain a copy of the license at Docs/cddl1.txt 29 1.1 christos # or http://www.opensolaris.org/os/licensing. 30 1.1 christos # See the License for the specific language governing permissions 31 1.1 christos # and limitations under the License. 32 1.1 christos # 33 1.1 christos # CDDL HEADER END 34 1.1 christos # 35 1.1 christos # ToDo: 36 1.1 christos # Trace readv() and writev(). 37 1.1 christos # 38 1.1 christos # 20-Feb-2006 Richard McDougall created this. 39 1.1 christos # 24-Feb-2006 Brendan Gregg tweaked code. 40 1.1 christos # 20-Mar-2006 " " tweaked code. 41 1.1 christos # 20-Mar-2006 " " last update. 42 1.1 christos 43 1.1 christos 44 1.1 christos ############################## 45 1.1 christos # --- Process Arguments --- 46 1.1 christos # 47 1.1 christos 48 1.1 christos ### Default variables 49 1.1 christos opt_read=0; opt_write=0 50 1.1 christos 51 1.1 christos ### Process options 52 1.1 christos while getopts hrw name 53 1.1 christos do 54 1.1 christos case $name in 55 1.1 christos r) opt_read=1 ;; 56 1.1 christos w) opt_write=1 ;; 57 1.1 christos h|?) cat <<-END >&2 58 1.1 christos USAGE: pfilestat [-r|-w] pid 59 1.1 christos -r # reads only 60 1.1 christos -w # writes only 61 1.1 christos eg, 62 1.1 christos pfilestat pid # default, r+w counts 63 1.1 christos pfilestat -r pid # read count only 64 1.1 christos END 65 1.1 christos exit 1 66 1.1 christos esac 67 1.1 christos done 68 1.1 christos shift `expr $OPTIND - 1` 69 1.1 christos 70 1.1 christos PID=$1 71 1.1 christos clearstr=`clear` 72 1.1 christos 73 1.1 christos if [ -z "$PID" ] 74 1.1 christos then 75 1.1 christos echo "Must supply pid" 76 1.1 christos exit 1 77 1.1 christos fi 78 1.1 christos 79 1.1 christos ### Option logic 80 1.1 christos if [ $opt_read -eq 0 -a $opt_write -eq 0 ]; then 81 1.1 christos opt_read=1; opt_write=1 82 1.1 christos fi 83 1.1 christos 84 1.1 christos 85 1.1 christos ################################# 86 1.1 christos # --- Main Program, DTrace --- 87 1.1 christos # 88 1.1 christos /usr/sbin/dtrace -n ' 89 1.1 christos #pragma D option quiet 90 1.1 christos 91 1.1 christos inline string CLEAR = "'$clearstr'"; 92 1.1 christos inline int OPT_read = '$opt_read'; 93 1.1 christos inline int OPT_write = '$opt_write'; 94 1.1 christos inline int PID = '$PID'; 95 1.1 christos 96 1.1 christos unsigned long long totaltime; 97 1.1 christos unsigned long long totalbytes; 98 1.1 christos 99 1.1 christos enum runstate { 100 1.1 christos READ, 101 1.1 christos WRITE, 102 1.1 christos OTHER 103 1.1 christos }; 104 1.1 christos 105 1.1 christos /* print header */ 106 1.1 christos dtrace:::BEGIN 107 1.1 christos { 108 1.1 christos printf("Tracing "); 109 1.1 christos OPT_read && OPT_write ? printf("reads and writes") : 1; 110 1.1 christos OPT_read && ! OPT_write ? printf("reads") : 1; 111 1.1 christos ! OPT_read && OPT_write ? printf("writes") : 1; 112 1.1 christos printf("..."); 113 1.1 christos totaltime = 0; 114 1.1 christos totalbytes = 0; 115 1.1 christos last = timestamp; 116 1.1 christos stamp = timestamp; 117 1.1 christos } 118 1.1 christos 119 1.1 christos /* sample reads */ 120 1.1 christos syscall::read:entry, 121 1.1 christos syscall::pread*:entry 122 1.1 christos /pid == PID && OPT_read/ 123 1.1 christos { 124 1.1 christos runstate = READ; 125 1.1 christos @logical["running", (uint64_t)0, ""] = sum(timestamp - last); 126 1.1 christos totaltime += timestamp - last; 127 1.1 christos last = timestamp; 128 1.1 christos 129 1.1 christos self->fd = arg0 + 1; 130 1.1 christos } 131 1.1 christos 132 1.1 christos fbt::fop_read:entry, 133 1.1 christos fbt::fop_write:entry 134 1.1 christos /self->fd/ 135 1.1 christos { 136 1.1 christos self->path = args[0]->v_path == 0 ? "<none>" : 137 1.1 christos cleanpath(args[0]->v_path); 138 1.1 christos } 139 1.1 christos 140 1.1 christos syscall::read:return, 141 1.1 christos syscall::pread*:return 142 1.1 christos /pid == PID && OPT_read/ 143 1.1 christos { 144 1.1 christos runstate = OTHER; 145 1.1 christos this->bytes = (int)arg0 > 0 ? (int)arg0 : 0; 146 1.1 christos @logical["read", self->fd - 1, self->path] = sum(timestamp - last); 147 1.1 christos @bytes["read", self->fd - 1, self->path] = sum(this->bytes); 148 1.1 christos totalbytes += this->bytes; 149 1.1 christos totaltime += timestamp - last; 150 1.1 christos last = timestamp; 151 1.1 christos self->path = 0; 152 1.1 christos self->fd = 0; 153 1.1 christos } 154 1.1 christos 155 1.1 christos 156 1.1 christos /* sample writes */ 157 1.1 christos syscall::write:entry, 158 1.1 christos syscall::pwrite*:entry 159 1.1 christos /pid == PID && OPT_write/ 160 1.1 christos { 161 1.1 christos runstate = WRITE; 162 1.1 christos @logical["running", (uint64_t)0, ""] = sum(timestamp - last); 163 1.1 christos totaltime += timestamp - last; 164 1.1 christos last = timestamp; 165 1.1 christos 166 1.1 christos self->fd = (int)arg0 + 1; 167 1.1 christos } 168 1.1 christos 169 1.1 christos syscall::write:return, 170 1.1 christos syscall::pwrite*:return 171 1.1 christos /pid == PID && OPT_write/ 172 1.1 christos { 173 1.1 christos runstate = OTHER; 174 1.1 christos this->bytes = (int)arg0 > 0 ? (int)arg0 : 0; 175 1.1 christos @logical["write", self->fd - 1, self->path] = sum(timestamp - last); 176 1.1 christos @bytes["write", self->fd - 1, self->path] = sum(this->bytes); 177 1.1 christos totalbytes += this->bytes; 178 1.1 christos totaltime += timestamp - last; 179 1.1 christos last = timestamp; 180 1.1 christos self->path = 0; 181 1.1 christos self->fd = 0; 182 1.1 christos } 183 1.1 christos 184 1.1 christos sched:::on-cpu 185 1.1 christos /pid == PID/ 186 1.1 christos { 187 1.1 christos @logical["waitcpu", (uint64_t)0, ""] = sum(timestamp - last); 188 1.1 christos totaltime += timestamp - last; 189 1.1 christos last = timestamp; 190 1.1 christos } 191 1.1 christos 192 1.1 christos 193 1.1 christos sched:::off-cpu 194 1.1 christos /pid == PID/ 195 1.1 christos { 196 1.1 christos @logical["running", (uint64_t)0, ""] = sum(timestamp - last); 197 1.1 christos totaltime += timestamp - last; 198 1.1 christos last = timestamp; 199 1.1 christos } 200 1.1 christos 201 1.1 christos sched:::sleep 202 1.1 christos /pid == PID/ 203 1.1 christos { 204 1.1 christos @logical["running", (uint64_t)0, ""] = sum(timestamp - last); 205 1.1 christos totaltime += timestamp - last; 206 1.1 christos last = timestamp; 207 1.1 christos } 208 1.1 christos 209 1.1 christos sched:::wakeup 210 1.1 christos /args[1]->pr_pid == PID && runstate == OTHER/ 211 1.1 christos { 212 1.1 christos @logical["sleep", (uint64_t)0, ""] = sum(timestamp - last); 213 1.1 christos totaltime += timestamp - last; 214 1.1 christos last = timestamp; 215 1.1 christos } 216 1.1 christos 217 1.1 christos sched:::wakeup 218 1.1 christos /args[1]->pr_pid == PID && runstate == READ/ 219 1.1 christos { 220 1.1 christos @logical["sleep-r", (uint64_t)0, ""] = sum(timestamp - last); 221 1.1 christos totaltime += timestamp - last; 222 1.1 christos last = timestamp; 223 1.1 christos } 224 1.1 christos 225 1.1 christos sched:::wakeup 226 1.1 christos /args[1]->pr_pid == PID && runstate == WRITE/ 227 1.1 christos { 228 1.1 christos @logical["sleep-w", (uint64_t)0, ""] = sum(timestamp - last); 229 1.1 christos totaltime += timestamp - last; 230 1.1 christos last = timestamp; 231 1.1 christos } 232 1.1 christos 233 1.1 christos sched:::enqueue 234 1.1 christos /args[1]->pr_pid == PID/ 235 1.1 christos { 236 1.1 christos @logical["waitcpu", (uint64_t)0, ""] = sum(timestamp - last); 237 1.1 christos totaltime += timestamp - last; 238 1.1 christos last = timestamp; 239 1.1 christos } 240 1.1 christos 241 1.1 christos sched:::dequeue 242 1.1 christos /args[1]->pr_pid == PID/ 243 1.1 christos { 244 1.1 christos @logical["waitcpu", (uint64_t)0, ""] = sum(timestamp - last); 245 1.1 christos totaltime += timestamp - last; 246 1.1 christos last = timestamp; 247 1.1 christos } 248 1.1 christos 249 1.1 christos /* print report */ 250 1.1 christos profile:::tick-5s 251 1.1 christos { 252 1.1 christos printf("%s", CLEAR); 253 1.1 christos normalize(@logical, totaltime / 100); 254 1.1 christos trunc(@logical, 10); 255 1.1 christos printf("%10s %7s %9s %-44s\n", "STATE", "FDNUM", "Time", "Filename"); 256 1.1 christos printa("%10s %7d %@8d%% %-44.44s\n", @logical); 257 1.1 christos trunc(@logical); 258 1.1 christos 259 1.1 christos delta = timestamp - stamp; 260 1.1 christos stamp = timestamp; 261 1.1 christos normalize(@bytes, (1024 * delta) / 1000000000); 262 1.1 christos trunc(@bytes, 10); 263 1.1 christos printf("\n%10s %7s %9s %-44s\n", "STATE", "FDNUM", "KB/s", 264 1.1 christos "Filename"); 265 1.1 christos printa("%10s %7d %@9d %-44.44s\n", @bytes); 266 1.1 christos trunc(@bytes); 267 1.1 christos 268 1.1 christos printf("\nTotal event time (ms): %d Total Mbytes/sec: %d\n", 269 1.1 christos totaltime / 1000000, 270 1.1 christos (totalbytes * 1000000000) / (delta * 1048576)); 271 1.1 christos 272 1.1 christos totaltime = 0; 273 1.1 christos totalbytes = 0; 274 1.1 christos last = timestamp; 275 1.1 christos } 276 1.1 christos 277 1.1 christos dtrace:::END 278 1.1 christos { 279 1.1 christos trunc(@logical); 280 1.1 christos trunc(@bytes); 281 1.1 christos } 282 1.1 christos ' 283