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

Last change on this file since 28186 was 28186, checked in by jmt12, 11 years ago

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

  • Property svn:executable set to *
File size: 4.7 KB
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 repository browser.