Back to home page

OSCL-LXR

 
 

    


0001 #!/usr/bin/perl -w
0002 # SPDX-License-Identifier: GPL-2.0-only
0003 # (c) 2010, Tom Zanussi <tzanussi@gmail.com>
0004 
0005 # read/write top
0006 #
0007 # Periodically displays system-wide r/w call activity, broken down by
0008 # pid.  If an [interval] arg is specified, the display will be
0009 # refreshed every [interval] seconds.  The default interval is 3
0010 # seconds.
0011 
0012 use 5.010000;
0013 use strict;
0014 use warnings;
0015 
0016 use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib";
0017 use lib "./Perf-Trace-Util/lib";
0018 use Perf::Trace::Core;
0019 use Perf::Trace::Util;
0020 use POSIX qw/SIGALRM SA_RESTART/;
0021 
0022 my $default_interval = 3;
0023 my $nlines = 20;
0024 my $print_thread;
0025 my $print_pending = 0;
0026 
0027 my %reads;
0028 my %writes;
0029 
0030 my $interval = shift;
0031 if (!$interval) {
0032     $interval = $default_interval;
0033 }
0034 
0035 sub syscalls::sys_exit_read
0036 {
0037     my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
0038     $common_pid, $common_comm, $common_callchain,
0039     $nr, $ret) = @_;
0040 
0041     print_check();
0042 
0043     if ($ret > 0) {
0044     $reads{$common_pid}{bytes_read} += $ret;
0045     } else {
0046     if (!defined ($reads{$common_pid}{bytes_read})) {
0047         $reads{$common_pid}{bytes_read} = 0;
0048     }
0049     $reads{$common_pid}{errors}{$ret}++;
0050     }
0051 }
0052 
0053 sub syscalls::sys_enter_read
0054 {
0055     my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
0056     $common_pid, $common_comm, $common_callchain,
0057     $nr, $fd, $buf, $count) = @_;
0058 
0059     print_check();
0060 
0061     $reads{$common_pid}{bytes_requested} += $count;
0062     $reads{$common_pid}{total_reads}++;
0063     $reads{$common_pid}{comm} = $common_comm;
0064 }
0065 
0066 sub syscalls::sys_exit_write
0067 {
0068     my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
0069     $common_pid, $common_comm, $common_callchain,
0070     $nr, $ret) = @_;
0071 
0072     print_check();
0073 
0074     if ($ret <= 0) {
0075     $writes{$common_pid}{errors}{$ret}++;
0076     }
0077 }
0078 
0079 sub syscalls::sys_enter_write
0080 {
0081     my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
0082     $common_pid, $common_comm, $common_callchain,
0083     $nr, $fd, $buf, $count) = @_;
0084 
0085     print_check();
0086 
0087     $writes{$common_pid}{bytes_written} += $count;
0088     $writes{$common_pid}{total_writes}++;
0089     $writes{$common_pid}{comm} = $common_comm;
0090 }
0091 
0092 sub trace_begin
0093 {
0094     my $sa = POSIX::SigAction->new(\&set_print_pending);
0095     $sa->flags(SA_RESTART);
0096     $sa->safe(1);
0097     POSIX::sigaction(SIGALRM, $sa) or die "Can't set SIGALRM handler: $!\n";
0098     alarm 1;
0099 }
0100 
0101 sub trace_end
0102 {
0103     print_unhandled();
0104     print_totals();
0105 }
0106 
0107 sub print_check()
0108 {
0109     if ($print_pending == 1) {
0110     $print_pending = 0;
0111     print_totals();
0112     }
0113 }
0114 
0115 sub set_print_pending()
0116 {
0117     $print_pending = 1;
0118     alarm $interval;
0119 }
0120 
0121 sub print_totals
0122 {
0123     my $count;
0124 
0125     $count = 0;
0126 
0127     clear_term();
0128 
0129     printf("\nread counts by pid:\n\n");
0130 
0131     printf("%6s  %20s  %10s  %10s  %10s\n", "pid", "comm",
0132        "# reads", "bytes_req", "bytes_read");
0133     printf("%6s  %-20s  %10s  %10s  %10s\n", "------", "--------------------",
0134        "----------", "----------", "----------");
0135 
0136     foreach my $pid (sort { ($reads{$b}{bytes_read} || 0) <=>
0137                    ($reads{$a}{bytes_read} || 0) } keys %reads) {
0138     my $comm = $reads{$pid}{comm} || "";
0139     my $total_reads = $reads{$pid}{total_reads} || 0;
0140     my $bytes_requested = $reads{$pid}{bytes_requested} || 0;
0141     my $bytes_read = $reads{$pid}{bytes_read} || 0;
0142 
0143     printf("%6s  %-20s  %10s  %10s  %10s\n", $pid, $comm,
0144            $total_reads, $bytes_requested, $bytes_read);
0145 
0146     if (++$count == $nlines) {
0147         last;
0148     }
0149     }
0150 
0151     $count = 0;
0152 
0153     printf("\nwrite counts by pid:\n\n");
0154 
0155     printf("%6s  %20s  %10s  %13s\n", "pid", "comm",
0156        "# writes", "bytes_written");
0157     printf("%6s  %-20s  %10s  %13s\n", "------", "--------------------",
0158        "----------", "-------------");
0159 
0160     foreach my $pid (sort { ($writes{$b}{bytes_written} || 0) <=>
0161             ($writes{$a}{bytes_written} || 0)} keys %writes) {
0162     my $comm = $writes{$pid}{comm} || "";
0163     my $total_writes = $writes{$pid}{total_writes} || 0;
0164     my $bytes_written = $writes{$pid}{bytes_written} || 0;
0165 
0166     printf("%6s  %-20s  %10s  %13s\n", $pid, $comm,
0167            $total_writes, $bytes_written);
0168 
0169     if (++$count == $nlines) {
0170         last;
0171     }
0172     }
0173 
0174     %reads = ();
0175     %writes = ();
0176 }
0177 
0178 my %unhandled;
0179 
0180 sub print_unhandled
0181 {
0182     if ((scalar keys %unhandled) == 0) {
0183     return;
0184     }
0185 
0186     print "\nunhandled events:\n\n";
0187 
0188     printf("%-40s  %10s\n", "event", "count");
0189     printf("%-40s  %10s\n", "----------------------------------------",
0190        "-----------");
0191 
0192     foreach my $event_name (keys %unhandled) {
0193     printf("%-40s  %10d\n", $event_name, $unhandled{$event_name});
0194     }
0195 }
0196 
0197 sub trace_unhandled
0198 {
0199     my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
0200     $common_pid, $common_comm, $common_callchain) = @_;
0201 
0202     $unhandled{$event_name}++;
0203 }