#!/usr/bin/perl -w # Report generation for plot-sgpdd # ================================ # The plot-sgpdd script is used to generate csv file and # instructions files for gnuplot from the output of sgpdd-survey script. # # The plot-sgpdd also creates .scr file that contains instructions # for gnuplot to plot the graph. After generating .dat and .scr files this # script invokes gnuplot to display graph. # # Syntax: # $ sgpdd-survey > log_filename # $ plot-sgpdd # [Note: 1. This script may need modifications whenever there will be # modifications in output format of sgpdd-survey script. # 2. Gnuplot version 4.0 or above is required.] sub usage() { print STDERR "Usage: $0 [options] \n"; print STDERR " $0 parses and plots graphs from the output of sgpdd-survey\n"; print STDERR " It generates text data files (.dat) and graphs (.png) using gnuplot.\n"; print STDERR "options:\n"; print STDERR " --rt: Subtitle for read graphs\n"; print STDERR " --wt: Subtitle for write graphs\n"; print STDERR " --y: Y-axis scale\n"; print STDERR "e.g. # $0 --rt=\"no prefetch\" --wt=\"WB disabled\" --y=500 sgpdd.summary\n"; exit 1; } # check whether gnuplot exists? system ("which gnuplot > /dev/null") == 0 or die "gnuplot does not exist, please install it and try again.\n"; # check whether gnuplot supports png $pngsupport = "ldd `which gnuplot` | grep -q libpng"; system ("$pngsupport") == 0 or die "gnuplot installed does not support png. Please install gnuplot to support png and try again.\n"; my @GraphTitle; #Subroutine to write .scr file that further used by gnuplot to plot the graph. sub write_scr_file() { my $op = $_[0]; print "generating plot $file-$rsz-$op.png\n"; open ( SCRFILE, "> $file-$rsz-$op.scr" ) or die "Can't open scr file for writing"; if ($op eq "rd") { $rwlabel = "Read"; } if ($op eq "wr") { $rwlabel = "Write"; } if ($opt_rdtitle || $opt_wrtitle) { if ($op eq "rd") { print SCRFILE "set title \"@GraphTitle\\n$rwlabel, Rsize = $rsz KBytes, $opt_rdtitle\"\n"; } if ($op eq "wr") { print SCRFILE "set title \"@GraphTitle\\n$rwlabel, Rsize = $rsz KBytes, $opt_wrtitle\"\n"; } } else { print SCRFILE "set title \"@GraphTitle\\n$rwlabel, Rsize = $rsz KBytes\"\n"; } print SCRFILE "set xlabel \"Threads\"\n"; print SCRFILE "set ylabel \"Speeds(MB/s)\"\n"; print SCRFILE "set logscale x\n"; print SCRFILE "set grid\n"; print SCRFILE "set terminal png\n"; print SCRFILE "set output \"/dev/null\"\n"; if ($opt_y != 0) { print SCRFILE "set yrange [ 0:$opt_y ]\n"; } else { print SCRFILE "set yrange [ 0: ]\n"; } my $plot = "plot"; $i = 2; my @numrgs = split " ", $regions; $xrange = 1; # generate instructions for gnuplot, with adjusting X-axes ranges foreach my $j (sort numerically split " ", $threads) { if ($op eq "wr") { $using = ( $i < $#numrgs ) ? $i : $#numrgs; printf SCRFILE "$plot \"$file-$rsz-$op.dat\" using 1:$using axes x%dy1 title \"write-obj$j\" with line\n", $xrange; } if ($op eq "rd") { $using = ( $i < $#numrgs ) ? $i : $#numrgs; printf SCRFILE "$plot \"$file-$rsz-$op.dat\" using 1:$using axes x%dy1 title \"read-obj$j\" with line\n", $xrange; } $i++; $plot = "replot"; } print SCRFILE "set output \"$file-$rsz-$op.png\"\n"; print SCRFILE "replot\n"; close SCRFILE; # invoke gnuplot to display graph. system ("gnuplot $file-$rsz-$op.scr") == 0 or die "ERROR: while ploting graph"; system ("rm $file-$rsz-$op.scr"); } sub check_data_file () { my $file=shift; my @values; my @tmp; open ( FILE, "< $file" ) or die "Can't open $file for reading"; while ( ) { @tmp = split; push @values, [ @tmp ]; } close FILE; for ( $j = 0; $j <= $#tmp; $j++) { my $sum=0; for ($i = 2; $i <= $#values ; $i ++) { $values [$i][$j] =~ "-" or $sum = $sum + $values [$i][$j]; } die "File: $file : $j column contains no data.\n" unless $sum != 0; } } sub numerically { $a <=> $b; } #Subroutine to write .dat file that further used by gnuplot to plot the graph. sub write_dat_file() { my $op = $_[0]; print "writing data $file-$rsz-$op.dat\n"; # Open .csv/.dat file for writing required columns from log file. my $datafile = "$file-$rsz-$op.dat"; open ( DATAFILE, "> $datafile" ) or die "Can't open csv $datafile for writing"; printf DATAFILE "%-6s", "0"; foreach my $j (sort numerically split " ", $regions) { printf DATAFILE "%-8s", "$op$j"; } # threads, line [7], strings foreach my $i (sort numerically split " ", $threads) { printf DATAFILE "\n%-6s", $i; # regions, line [5], column foreach my $j (sort numerically split " ", $regions) { if (($op eq "rd" && $rdwr) || ($op eq "wr" && $wrrd) || ($readop) || ($writeop)) { if ( $out{$i}{$j} ) { printf DATAFILE "%-8s", $out{$i}{$j}; } else { printf DATAFILE "%-8s", "-"; } } else { if (($j <= 1 && $out{$i}{$j - 1})) { printf DATAFILE "%-8s", $out{$i}{$j - 1}; }elsif ($out{$i}{$j + 1} && $j > 1) { printf DATAFILE "%-8s", $out{$i}{$j + 1}; } else { printf DATAFILE "%-8s", "-"; } } } } close DATAFILE; &check_data_file ( $datafile ); } if ( !$ARGV[0] ) { usage(); } $regions = ""; $threads = ""; $count = 0; $wrrd = 0; $rdwr = 0; $writeop = 0; $readop = 0; $rsz = 0; $opt_rdtitle = ""; $opt_wrtitle = ""; $opt_y = 0; # Command line parameter parsing use Getopt::Long; GetOptions ('help' => \$opt_help, 'rt=s' => \$opt_rdtitle, 'wt=s' => \$opt_wrtitle, 'y=i' => \$opt_y) or usage(); if ($opt_help) { usage(); } $file = $ARGV[0]; open ( PFILE, "$file") or die "Can't open $file"; LABEL: while ( ) { chomp; @line = split( /\s+/ ); if ($line[27] && $count != 0) { print "invalid file format\n"; exit 1; } if ($count == 0) { @GraphTitle = @line; $count++; next LABEL; } if ($line[8]) { if ($line[8] eq "ENOMEM") { next LABEL; } } if (!$rsz && $line[3]) { $rsz = $line[3]; } if ($rsz != $line[3]) { if($readop) { &write_dat_file("rd"); &write_scr_file("rd"); } if($writeop) { &write_dat_file("wr"); &write_scr_file("wr"); } if ($wrrd || $rdwr) { &write_dat_file("rd"); &write_scr_file("rd"); &write_dat_file("wr"); &write_scr_file("wr"); } $rsz = $line[3]; $regions = ""; $threads = ""; } #print "rg$line[5] th$line[7] w$line[9] r$line[$rindex]\n"; $rindex = 18; if ($line[18]) { if ($line[10] eq "failed") { $rindex = 12; } if ($line[8] eq "write" && $line[17] eq "read") { $wrrd = 1; } if ($line[8] eq "read" && $line[17] eq "write") { $rdwr = 1; } } else { if ($line[8] eq "write" && $line[9]) { $writeop = 1; } if ($line[8] eq "read" && $line[9]) { $readop = 1; } } if ($wrrd || $rdwr) { $out{$line[7]}{$line[5]} = $line[9]; if ($line[$rindex+1]) { if (!($line[$rindex+1] eq "failed")) { goto LABEL2; } } else { LABEL2: if ($line[5] <= 1 ) { $out{$line[7]}{$line[5] - 1} = $line[$rindex]; } else { $out{$line[7]}{$line[5] + 1} = $line[$rindex]; } } } if ($writeop) { $out{$line[7]}{$line[5]} = $line[9]; } if ($readop) { $out{$line[7]}{$line[5]} = $line[9]; } $regions .= " $line[5]" unless $regions =~ $line[5]; $threads .= " $line[7]" unless $threads =~ $line[7]; $count++; } close PFILE; if ($count > 1 && $rsz) { if($readop) { &write_dat_file("rd"); &write_scr_file("rd"); } if($writeop) { &write_dat_file("wr"); &write_scr_file("wr"); } if ($wrrd || $rdwr) { &write_dat_file("rd"); &write_scr_file("rd"); &write_dat_file("wr"); &write_scr_file("wr"); } } else { print "Invalid log file format\n"; }