root/gs2-extensions/parallel-building/trunk/src/bin/script/iotop_report.pl @ 28186

Revision 28186, 4.7 KB (checked in by jmt12, 7 years ago)

A (failed) attempt to use the unix iotop tool to determine IO percentage

  • Property svn:executable set to *
Line 
1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
6use Time::HiRes qw( gettimeofday tv_interval );
7
8# 0. Initialize
9our $start_time = [gettimeofday()];
10my $data = {};
11my @accepted_commands =
12( 'import.pl',
13  'HandBrakeCLI',
14  'hive2_ffmpegsvn',
15  'mediainfo',
16  'cp'
17);
18my $accepted_commands_pattern = '(' . join('|', @accepted_commands) . ')';
19
20print '='x80 . "\n";
21print '='x30 . '    IOTop Report    ' . '='x30 . "\n";
22print '='x80 . "\n\n";
23
24# 1. Read in arguments
25print 'Arguments:' . "\n";
26if (!defined $ARGV[0] || !-f $ARGV[0])
27{
28  &printError('Missing iotop log file or not a file.');
29  &printUsage();
30  &exitProgram();
31}
32my $iotop_file = $ARGV[0];
33print "\t" . 'IOTop file: ' . $iotop_file . "\n";
34print "\n";
35
36# 2. Loop through iolog file
37print 'Process:' . "\n";
38print "\t" . ' * Reading IOTop log file... ';
39my $iolog_fh;
40open($iolog_fh, '<:utf8', $iotop_file);
41if ($iolog_fh)
42{
43  my $line = '';
44  while ($line = <$iolog_fh>)
45  {
46    # Look for lines describing process IO activity
47    if ($line =~ /(\d\d:\d\d:\d\d)\s+(\d+)\s+([^\s]+)\s+([^\s]+)\s+(\d+\.\d+\s[BKMG](?:\/s)?)\s+(\d+\.\d+\s[BKMG](?:\/s)?)\s+(\d+\.\d+)\s\%\s+(\d+\.\d+)\s\%\s+(.*)/)
48    {
49      my $timestamp  = $1;
50      my $pid        = $2;
51      my $priority   = $3;
52      my $user       = $4;
53      my $disk_read  = $5;
54      my $disk_write = $6;
55      my $swap_in    = $7;
56      my $io_percent = $8;
57      my $command    = $9;
58      # Shorten command so it is more ueful
59      $command = &parseCommand($command);
60      # If we are not ignoring these commands...
61      if ($command =~ /$accepted_commands_pattern/)
62      {
63        # Store this information for a new record
64        if (!defined $data->{$pid})
65        {
66          $data->{$pid} = {'command'    => $command,
67                           'start_time' => $timestamp,
68                           'end_time'   => $timestamp,
69                           'occurances' => 1,
70                           'iopercents' => $io_percent
71                          };
72        }
73        # or update an existing record
74        else
75        {
76          $data->{$pid}->{'end_time'} = $timestamp;
77          $data->{$pid}->{'occurances'}++;
78          $data->{$pid}->{'iopercents'} .= ':' . $io_percent
79        }
80      }
81    }
82  }
83  close($iolog_fh);
84}
85else
86{
87  &printError('Failed to open file for reading: ' . $iotop_file);
88  &exitProgram();
89}
90print 'Done!' . "\n";
91
92# 3. Print report to CSV
93print "\t" . ' * Writing report... ' . "\n";;
94my $ioreport_fh;
95open($ioreport_fh, '>:utf8', 'ioreport.csv');
96my $temp_sum = 0;
97if ($ioreport_fh)
98{
99  print 'PID,    DUR, TIME, IOPCT, COMMAND' . "\n";
100  foreach my $pid (sort keys %{$data})
101  {
102    my $start_seconds = &parseEpoc($data->{$pid}->{'start_time'});
103    my $end_seconds = &parseEpoc($data->{$pid}->{'end_time'});
104    my $duration = $end_seconds - $start_seconds;
105
106    my @io_percents = split(/:/, $data->{$pid}->{'iopercents'});
107    my $io_sum = 0.00;
108    foreach my $io_percent (@io_percents)
109    {
110      if ($io_percent > 0)
111      {
112        $temp_sum += $io_percent;
113      }
114      $io_sum += $io_percent;
115    }
116    my $io_avg = 0.00;
117    if ($io_sum > 0)
118    {
119      $io_avg = $io_sum / $data->{$pid}->{'occurances'};
120    }
121    print sprintf('%5d, %4d, %4d, %5.2f, "%s"', $pid, $duration, $data->{$pid}->{'occurances'}, $io_avg, $data->{$pid}->{'command'}) . " [" . $data->{$pid}->{'iopercents'} . "]\n";
122  }
123  close($ioreport_fh);
124}
125else
126{
127  &printError('Failed to open file for writing: ./ioreport.csv');
128}
129print 'Done!' . "\n\n";
130
131print "Sum: " . $temp_sum . "\n";
132
133&exitProgram();
134
135# Should never get here
136exit;
137
138###### FUNCTIONS ######
139
140## @function
141#
142sub exitProgram
143{
144  my $end_time = [gettimeofday()];
145  my $elapsed = tv_interval($start_time, $end_time);
146  print sprintf('%s  Complete in %7.3f seconds!  %1$s', '='x24, $elapsed) . "\n\n";
147  exit;
148}
149## exitProgram() ##
150
151
152## @function
153#
154sub parseCommand
155{
156  my ($full_command) = @_;
157  my $command;
158  # Anything that starts with perl, we extract just the script name
159  if ($full_command =~ /perl.*?([a-z0-9]+\.pl)/)
160  {
161    $command = $1;
162  }
163  elsif ($full_command =~ /^([^\s]+)/)
164  {
165    $command = $1;
166  }
167  # Everything else we shorten to just 12 characters
168  else
169  {
170    $command = substr($full_command, 0, 12);
171  }
172  return $command;
173}
174## parseCommand() ##
175
176
177## @function
178#
179sub parseEpoc
180{
181  my ($timestamp) = @_;
182  my @parts = split(/:/, $timestamp);
183  my $seconds = $parts[2];         # Seconds
184  $seconds += $parts[1] * 60;      # Minutes
185  $seconds += $parts[0] * 60 * 60; # Hours
186  return $seconds;
187}
188## parseEpoc() ##
189
190
191## @function
192#
193sub printError
194{
195  my ($msg) = @_;
196  print 'Error! ' . $msg . "\n";
197}
198## printError() ##
199
200
201## @function
202#
203sub printUsage
204{
205  print 'Usage: iotop_report.pl <iotop log file>' . "\n\n";
206}
207## printUsage() ##
Note: See TracBrowser for help on using the browser.