#!/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]; my $rwlabel = $_[1]; print "generating plot $file-$rsz-$op.png\n"; open ( SCRFILE, "> $file-$rsz-$op.scr" ) or die "Can't open scr file for writing"; if ($opt_rdtitle || $opt_wrtitle) { if ($op eq "rd") { print SCRFILE "set title \"@GraphTitle\\n$rwlabel, " . "Rsize = $rsz, $lun LUNs, $opt_rdtitle\"\n"; } if ($op eq "wr") { print SCRFILE "set title \"@GraphTitle\\n$rwlabel, " . "Rsize = $rsz, $lun LUNs, $opt_wrtitle\"\n"; } } else { print SCRFILE "set title \"@GraphTitle\\n$rwlabel, " . "Rsize = $rsz, $lun LUNs\"\n"; } print SCRFILE "set xlabel \"Threads/LUN\"\n"; print SCRFILE "set ylabel \"Throughput (MiB/s)\"\n"; print SCRFILE "set logscale x\n"; print SCRFILE "set grid\n"; print SCRFILE "set key right bottom\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; $xrange = 1; # generate instructions for gnuplot, with adjusting X-axes ranges for ($j = $first_crg; $j <= $crg ; $j = $j + $j) { $tmp=$j/$lun; printf SCRFILE "$plot \"$file-$rsz-$op.dat\" " . "using 1:$i:xticlabels(1) axes x%dy1 " . "title \"$tmp crg/LUN\" " . "with linespoints lw 2\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"); } #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", "thrd"; for ($j = $first_crg; $j <= $crg ; $j = $j + $j) { $tmp = $j/$lun; printf DATAFILE "%-10s", "$tmp-crg"; } for ( $i = $first_thread; $i <= $thread; $i = $i + $i ) { printf DATAFILE "\n%-6s", $i/$lun; for ($j = $first_crg; $j <= $crg ; $j = $j + $j) { if ($op eq "rd") { if ( $ard{$i}{$j} ) { printf DATAFILE "%-10s", $ard{$i}{$j}; } else { printf DATAFILE "%-10s", "-"; } } elsif ($op eq "wr" ) { if ( $awr{$i}{$j} ) { printf DATAFILE "%-10s", $awr{$i}{$j}; } else { printf DATAFILE "%-10s", "-"; } } } } close DATAFILE; } #Subroutine to call .scr and .dat file write routines. sub write_files() { for ($cnt = 0; $cnt < @operations; $cnt = $cnt + 1) { if($operations[$cnt] eq "read") { &write_dat_file("rd"); &write_scr_file("rd", "read"); } elsif ($operations[$cnt] eq "write") { &write_dat_file("wr"); &write_scr_file("wr", "write"); } } } if ( !$ARGV[0] ) { usage(); } $crg = 0; $thread = 0; $first_crg = 1; $first_thread = 1; $count = 0; $rsz = 0; $opt_rdtitle = ""; $opt_wrtitle = ""; $opt_y = 0; $cnt = 0; @operations = (); # 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; # replace error strings to ensure same ordering of line fields s/failed/failed . . . . ./g; @line = split( /\s+/ ); if ($count == 0) { @GraphTitle = @line[0 .. 6]; $count++; next LABEL; } # output format # dev 1 sz 1048576K rsz 1024K crg 1 thr 8 write 604.55 [ 606.43, 606.43] read 754.02 [ 756.95, 756.95] $linelen = @line; if ($linelen < 11) { print "invalid file format at line $count\n"; exit 1; } if ($line[10]) { if ($line[10] eq "ENOMEM") { next LABEL; } } if (!$rsz || $rsz ne $line[5]) { &write_files() unless !$rsz; $cnt = 0; $lun = $line[1]; $rsz = $line[5]; $first_crg = $line[7]; $first_thread = $line[9]; for ($i = 10; $i <= $linelen; $i = $i + 5) { if ($line[$i]) { $operations[$cnt] = $line[$i]; $cnt++; } } } for ($i = 0; $i < @operations; $i++) { if ($operations[$i] eq "read") { $ard{$line[9]}{$line[7]} = $line[$i * 5 + 11]; } elsif ($operations[$i] eq "write") { $awr{$line[9]}{$line[7]} = $line[$i * 5 + 11]; } } if ( $crg < $line[7] ) { $crg = $line[7]; } if ( $thread < $line[9] ) { $thread = $line[9]; } $count++; } close PFILE; if ($count > 1 && $rsz) { &write_files() } else { print "Invalid log file format\n"; }