linux/tools/perf/scripts/perl/rwtop.pl
<<
>>
Prefs
   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