Whamcloud - gitweb
LU-3154: Fix plot-sgpdd to match new sgpdd-survey output format
[fs/lustre-release.git] / lustre-iokit / sgpdd-survey / plot-sgpdd
1 #!/usr/bin/perl -w
2 # Report generation for plot-sgpdd
3 # ================================
4 #        The plot-sgpdd script is used to generate csv file and
5 # instructions files for gnuplot from the output of sgpdd-survey script.
6 #
7 #        The plot-sgpdd also creates .scr file that contains instructions
8 # for gnuplot to plot the graph. After generating .dat and .scr files this
9 # script invokes gnuplot to display graph.
10 #
11 # Syntax:
12 # $ sgpdd-survey > log_filename
13 # $ plot-sgpdd <log_filename>
14 # [Note: 1. This script may need modifications whenever there will be
15 #           modifications in output format of sgpdd-survey script.
16 #        2. Gnuplot version 4.0 or above is required.]
17
18 sub usage() 
19 {
20         print STDERR "Usage: $0 [options] <log_filename>\n";
21         print STDERR "  $0 parses and plots graphs from the output of sgpdd-survey\n";
22         print STDERR "  It generates text data files (.dat) and graphs (.png) using gnuplot.\n";
23         print STDERR "options:\n";
24         print STDERR "  --rt: Subtitle for read graphs\n";
25         print STDERR "  --wt: Subtitle for write graphs\n";
26         print STDERR "  --y: Y-axis scale\n";
27         print STDERR "e.g. # $0 --rt=\"no prefetch\" --wt=\"WB disabled\" --y=500 sgpdd.summary\n";
28         exit 1;
29 }
30
31 # check whether gnuplot exists?
32 system ("which gnuplot > /dev/null") == 0 or die "gnuplot does not exist, please install it and try again.\n";
33
34 # check whether gnuplot supports png
35 $pngsupport = "ldd `which gnuplot` | grep -q libpng";
36 system ("$pngsupport") == 0 or die "gnuplot installed does not support png.
37         Please install gnuplot to support png and try again.\n"; 
38
39 my @GraphTitle;
40
41 #Subroutine to write .scr file that further used by gnuplot to plot the graph.
42 sub write_scr_file() {
43         my $op = $_[0];
44         print "generating plot $file-$rsz-$op.png\n";
45         open ( SCRFILE, "> $file-$rsz-$op.scr" ) or die "Can't open scr file for writing";
46         if ($op eq "rd") {
47                 $rwlabel = "Read";
48         }
49         if ($op eq "wr") {
50                 $rwlabel = "Write";
51         }
52         
53         if ($opt_rdtitle || $opt_wrtitle) {
54                 if ($op eq "rd") {
55                         print SCRFILE "set title \"@GraphTitle\\n$rwlabel, Rsize = $rsz KBytes, $opt_rdtitle\"\n";
56                 }
57                 if ($op eq "wr") {
58                         print SCRFILE "set title \"@GraphTitle\\n$rwlabel, Rsize = $rsz KBytes, $opt_wrtitle\"\n";
59                 }
60         } else {
61                 print SCRFILE "set title \"@GraphTitle\\n$rwlabel, Rsize = $rsz KBytes\"\n";
62         }
63         print SCRFILE "set xlabel \"Threads\"\n";
64         print SCRFILE "set ylabel \"Speeds(MB/s)\"\n";
65         print SCRFILE "set logscale x\n";
66         print SCRFILE "set grid\n";
67         print SCRFILE "set terminal png\n";
68         print SCRFILE "set output \"/dev/null\"\n";
69         if ($opt_y != 0) {
70                 print SCRFILE "set yrange [ 0:$opt_y ]\n";
71         } else {
72                 print SCRFILE "set yrange [ 0: ]\n";
73         }
74
75         my $plot = "plot";
76         $i = 2;
77         my @numrgs = split " ", $regions;
78         $xrange = 1;
79         # generate instructions for gnuplot, with adjusting X-axes ranges
80         
81         foreach my $j (sort numerically split " ", $threads) {
82                 if ($op eq "wr") {
83                         $using = ( $i < $#numrgs ) ? $i : $#numrgs;
84                         printf SCRFILE "$plot \"$file-$rsz-$op.dat\" using 1:$using axes x%dy1 title \"write-obj$j\" with line\n", $xrange;
85                 }
86                 if ($op eq "rd") {
87                         $using = ( $i < $#numrgs ) ? $i : $#numrgs;
88                         printf SCRFILE "$plot \"$file-$rsz-$op.dat\" using 1:$using axes x%dy1 title \"read-obj$j\" with line\n", $xrange;
89                 }
90                 $i++;
91                 $plot = "replot";
92         }
93         print SCRFILE "set output \"$file-$rsz-$op.png\"\n";
94         print SCRFILE "replot\n";
95         close SCRFILE;
96         # invoke gnuplot to display graph.
97         system ("gnuplot $file-$rsz-$op.scr") == 0 or die "ERROR: while ploting graph";
98         system ("rm $file-$rsz-$op.scr");
99 }
100
101 sub check_data_file () {
102         my $file=shift;
103         my @values;
104         my @tmp;
105
106         open ( FILE, "< $file" ) or die "Can't open $file for reading";
107         while ( <FILE> ) {
108                 @tmp = split;
109                 push @values, [ @tmp ];
110         }
111         close FILE;
112
113         for ( $j = 0; $j <= $#tmp; $j++) {
114                 my $sum=0;
115                 for ($i = 2; $i <= $#values ; $i ++) {
116                         $values [$i][$j] =~ "-" or $sum = $sum + $values [$i][$j];
117                 }
118                 die "File: $file : $j column contains no data.\n" unless $sum != 0;
119         }
120 }
121
122 sub numerically { $a <=> $b; }
123
124 #Subroutine to write .dat file that further used by gnuplot to plot the graph.
125 sub write_dat_file() {
126         my $op = $_[0];
127         print "writing data $file-$rsz-$op.dat\n";
128         # Open .csv/.dat file for writing required columns from log file.
129         my $datafile = "$file-$rsz-$op.dat";
130         open ( DATAFILE, "> $datafile" ) or die "Can't open csv $datafile for writing";
131         printf DATAFILE "%-6s", "0";
132         
133         foreach my $j (sort numerically split " ", $regions) {
134                 printf DATAFILE "%-8s", "$op$j";
135         }
136
137         # threads, line [7], strings
138         foreach my $i (sort numerically split " ", $threads) {
139                 printf DATAFILE "\n%-6s", $i;
140
141                 # regions, line [5], column
142                 foreach my $j (sort numerically split " ", $regions) {
143                         if (($op eq "rd" && $rdwr) || ($op eq "wr" && $wrrd) || ($readop) || ($writeop)) {
144                                 if ( $out{$i}{$j} ) {
145                                         printf DATAFILE "%-8s", $out{$i}{$j};
146                                 } else {
147                                         printf DATAFILE "%-8s", "-";
148                                 }
149                         } else {
150                                 if (($j <= 1 && $out{$i}{$j - 1})) {
151                                         printf DATAFILE "%-8s", $out{$i}{$j - 1};
152                                 }elsif ($out{$i}{$j + 1} && $j > 1) {
153                                         printf DATAFILE "%-8s", $out{$i}{$j + 1};
154                                 } else {
155                                         printf DATAFILE "%-8s", "-";
156                                 }
157                         }
158                 }
159         }
160         close DATAFILE;
161         &check_data_file ( $datafile );
162 }
163
164 if ( !$ARGV[0] ) {
165         usage();
166 }
167 $regions = "";
168 $threads = "";
169 $count = 0;
170 $wrrd = 0;
171 $rdwr = 0;
172 $writeop = 0;
173 $readop = 0;
174 $rsz = 0;
175 $opt_rdtitle = "";
176 $opt_wrtitle = "";
177 $opt_y = 0;
178 # Command line parameter parsing
179 use Getopt::Long;
180 GetOptions ('help' => \$opt_help, 'rt=s' => \$opt_rdtitle, 'wt=s' => \$opt_wrtitle, 'y=i' => \$opt_y) or usage(); 
181 if ($opt_help) {
182         usage();
183 }
184 $file = $ARGV[0];
185
186 open ( PFILE, "$file") or die "Can't open $file";
187 LABEL: while ( <PFILE> ) {
188         chomp;
189         @line = split( /\s+/ );
190         # Remove the 'K' after rsz
191         $frsz = substr($line[3], 0, -1);
192         if ($line[28] && $count != 0) {
193                 print "invalid file format\n";
194                 exit 1;
195         } 
196         if ($count == 0) {
197                 @GraphTitle = @line;
198                 $count++;
199                 next LABEL;
200         }
201         if ($line[8]) {
202                 if ($line[8] eq "ENOMEM") {
203                         next LABEL;
204                 }
205         }
206         if (!$rsz && $frsz) {
207                 $rsz = $frsz
208         }
209         if ($rsz != $frsz) {
210                 if($readop) {
211                         &write_dat_file("rd");
212                         &write_scr_file("rd");
213                 }
214                 if($writeop) {
215                         &write_dat_file("wr");
216                         &write_scr_file("wr");
217                 }
218                 if ($wrrd || $rdwr) {
219                         &write_dat_file("rd");
220                         &write_scr_file("rd");
221                         &write_dat_file("wr");
222                         &write_scr_file("wr");
223                 }
224                 $rsz = substr($line[3],0,-1);;
225                 $regions = "";
226                 $threads = "";
227         }
228         $rindex = 20;
229         print "DEBUG rg$line[7] th$line[9] w$line[11] r$line[$rindex]\n";
230         if ($line[18]) {
231                 if ($line[12] eq "failed") {
232                         $rindex = 12;
233                 }
234                 if ($line[10] eq "write" && $line[19] eq "read") {
235                         $wrrd = 1;
236                 }
237                 if ($line[10] eq "read" && $line[19] eq "write") {
238                         $rdwr = 1;
239                 }
240         } else {
241                 if ($line[10] eq "write" && $line[11]) {
242                         $writeop = 1;
243                 }
244                 if ($line[10] eq "read" && $line[11]) {
245                         $readop = 1;
246                 }
247         }
248         if ($wrrd || $rdwr) {
249                 $out{$line[9]}{$line[7]} = $line[11];
250                 if ($line[$rindex+1]) {
251                         if (!($line[$rindex+1] eq "failed")) {
252                                 goto LABEL2;
253                         }
254                 } else {
255 LABEL2:                 if ($line[7] <= 1 ) {
256                                 $out{$line[9]}{$line[7] - 1} = $line[$rindex];
257                         } else {
258                                 $out{$line[9]}{$line[7] + 1} = $line[$rindex];
259                         }
260                 }
261         }
262         if ($writeop) {
263                 $out{$line[9]}{$line[7]} = $line[11];
264         }
265         if ($readop) {
266                 $out{$line[9]}{$line[7]} = $line[11];
267         }
268         $regions .= " $line[7]" unless $regions =~ $line[7];
269         $threads .= " $line[9]" unless $threads =~ $line[9];
270         $count++;
271 }
272 close PFILE;
273 if ($count > 1 && $rsz) {
274         if($readop) {
275                 &write_dat_file("rd");
276                 &write_scr_file("rd");
277         }
278         if($writeop) {
279                 &write_dat_file("wr");
280                 &write_scr_file("wr");
281         }
282         if ($wrrd || $rdwr) {
283                 &write_dat_file("rd");
284                 &write_scr_file("rd");
285                 &write_dat_file("wr");
286                 &write_scr_file("wr");
287         }
288 } else {
289         print "Invalid log file format\n";
290 }