1#!/usr/bin/perl -w 2# (c) 2010, Tom Zanussi <tzanussi@gmail.com> 3# Licensed under the terms of the GNU GPL License version 2 4 5# read/write top 6# 7# Periodically displays system-wide r/w call activity, broken down by 8# pid. If an [interval] arg is specified, the display will be 9# refreshed every [interval] seconds. The default interval is 3 10# seconds. 11 12use 5.010000; 13use strict; 14use warnings; 15 16use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib"; 17use lib "./Perf-Trace-Util/lib"; 18use Perf::Trace::Core; 19use Perf::Trace::Util; 20 21my $default_interval = 3; 22my $nlines = 20; 23my $print_thread; 24my $print_pending = 0; 25 26my %reads; 27my %writes; 28 29my $interval = shift; 30if (!$interval) { 31 $interval = $default_interval; 32} 33 34sub syscalls::sys_exit_read 35{ 36 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, 37 $common_pid, $common_comm, 38 $nr, $ret) = @_; 39 40 print_check(); 41 42 if ($ret > 0) { 43 $reads{$common_pid}{bytes_read} += $ret; 44 } else { 45 if (!defined ($reads{$common_pid}{bytes_read})) { 46 $reads{$common_pid}{bytes_read} = 0; 47 } 48 $reads{$common_pid}{errors}{$ret}++; 49 } 50} 51 52sub syscalls::sys_enter_read 53{ 54 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, 55 $common_pid, $common_comm, 56 $nr, $fd, $buf, $count) = @_; 57 58 print_check(); 59 60 $reads{$common_pid}{bytes_requested} += $count; 61 $reads{$common_pid}{total_reads}++; 62 $reads{$common_pid}{comm} = $common_comm; 63} 64 65sub syscalls::sys_exit_write 66{ 67 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, 68 $common_pid, $common_comm, 69 $nr, $ret) = @_; 70 71 print_check(); 72 73 if ($ret <= 0) { 74 $writes{$common_pid}{errors}{$ret}++; 75 } 76} 77 78sub syscalls::sys_enter_write 79{ 80 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, 81 $common_pid, $common_comm, 82 $nr, $fd, $buf, $count) = @_; 83 84 print_check(); 85 86 $writes{$common_pid}{bytes_written} += $count; 87 $writes{$common_pid}{total_writes}++; 88 $writes{$common_pid}{comm} = $common_comm; 89} 90 91sub trace_begin 92{ 93 $SIG{ALRM} = \&set_print_pending; 94 alarm 1; 95} 96 97sub trace_end 98{ 99 print_unhandled(); 100 print_totals(); 101} 102 103sub print_check() 104{ 105 if ($print_pending == 1) { 106 $print_pending = 0; 107 print_totals(); 108 } 109} 110 111sub set_print_pending() 112{ 113 $print_pending = 1; 114 alarm $interval; 115} 116 117sub print_totals 118{ 119 my $count; 120 121 $count = 0; 122 123 clear_term(); 124 125 printf("\nread counts by pid:\n\n"); 126 127 printf("%6s %20s %10s %10s %10s\n", "pid", "comm", 128 "# reads", "bytes_req", "bytes_read"); 129 printf("%6s %-20s %10s %10s %10s\n", "------", "--------------------", 130 "----------", "----------", "----------"); 131 132 foreach my $pid (sort { ($reads{$b}{bytes_read} || 0) <=> 133 ($reads{$a}{bytes_read} || 0) } keys %reads) { 134 my $comm = $reads{$pid}{comm} || ""; 135 my $total_reads = $reads{$pid}{total_reads} || 0; 136 my $bytes_requested = $reads{$pid}{bytes_requested} || 0; 137 my $bytes_read = $reads{$pid}{bytes_read} || 0; 138 139 printf("%6s %-20s %10s %10s %10s\n", $pid, $comm, 140 $total_reads, $bytes_requested, $bytes_read); 141 142 if (++$count == $nlines) { 143 last; 144 } 145 } 146 147 $count = 0; 148 149 printf("\nwrite counts by pid:\n\n"); 150 151 printf("%6s %20s %10s %13s\n", "pid", "comm", 152 "# writes", "bytes_written"); 153 printf("%6s %-20s %10s %13s\n", "------", "--------------------", 154 "----------", "-------------"); 155 156 foreach my $pid (sort { ($writes{$b}{bytes_written} || 0) <=> 157 ($writes{$a}{bytes_written} || 0)} keys %writes) { 158 my $comm = $writes{$pid}{comm} || ""; 159 my $total_writes = $writes{$pid}{total_writes} || 0; 160 my $bytes_written = $writes{$pid}{bytes_written} || 0; 161 162 printf("%6s %-20s %10s %13s\n", $pid, $comm, 163 $total_writes, $bytes_written); 164 165 if (++$count == $nlines) { 166 last; 167 } 168 } 169 170 %reads = (); 171 %writes = (); 172} 173 174my %unhandled; 175 176sub print_unhandled 177{ 178 if ((scalar keys %unhandled) == 0) { 179 return; 180 } 181 182 print "\nunhandled events:\n\n"; 183 184 printf("%-40s %10s\n", "event", "count"); 185 printf("%-40s %10s\n", "----------------------------------------", 186 "-----------"); 187 188 foreach my $event_name (keys %unhandled) { 189 printf("%-40s %10d\n", $event_name, $unhandled{$event_name}); 190 } 191} 192 193sub trace_unhandled 194{ 195 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, 196 $common_pid, $common_comm) = @_; 197 198 $unhandled{$event_name}++; 199} 200