iozone_visualizer.pl 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. #!/usr/bin/env perl
  2. use warnings;
  3. use strict;
  4. # arguments: one of more report files
  5. #
  6. # Christian Mautner <christian * mautner . ca>, 2005-10-31
  7. # Marc Schoechlin <ms * 256bit.org>, 2007-12-02
  8. # Pär Karlsson <feinorgh * gmail . com>, 2012-07-24
  9. #
  10. # This script is just a hack :-)
  11. #
  12. # This script is based loosely on the Generate_Graph set
  13. # of scripts that come with iozone, but is a complete re-write
  14. #
  15. # The main reason to write this was the need to compare the behaviour of
  16. # two or more different setups, for tuning filesystems or
  17. # comparing different pieces of hardware.
  18. #
  19. # This has been updated (2012) to take the new gnuplot 4 syntax into account,
  20. # and some general perl cleanups, despite its "hack" status.
  21. # It also requires some perl libraries to funktion, specifically
  22. # Readonly and List::MoreUtils which are not included in the standard
  23. # perl in most distributions.
  24. #
  25. # This script is in the public domain, too short and too trivial
  26. # to deserve a copyright.
  27. #
  28. # Simply run iozone like, for example, ./iozone -a -g 4G > config1.out (if your machine has 4GB)
  29. #
  30. # and then run perl report.pl config1.out
  31. # or get another report from another box into config2.out and run
  32. # perl report.pl config1.out config2.out
  33. # the look in the report_* directory for .png
  34. #
  35. # If you don't like png or the graphic size, search for "set terminal" in this file and put whatever gnuplot
  36. # terminal you want. Note I've also noticed that gnuplot switched the set terminal png syntax
  37. # a while back, you might need "set terminal png small size 900,700"
  38. use Carp;
  39. use English qw(-no_match_vars);
  40. use Getopt::Long;
  41. use List::MoreUtils qw(any);
  42. use Readonly;
  43. Readonly my $EMPTY => q{};
  44. Readonly my $SPACE => q{ };
  45. my $column;
  46. my %columns;
  47. my $datafile;
  48. my @datafiles;
  49. my $outdir;
  50. my $report;
  51. my $nooffset = 0;
  52. my @reports;
  53. my @split;
  54. my $size3d;
  55. my $size2d;
  56. # evaluate options
  57. GetOptions(
  58. '3d=s' => \$size3d,
  59. '2d=s' => \$size2d,
  60. 'nooffset' => \$nooffset
  61. );
  62. if ( not defined $size3d ) {
  63. $size3d = '1280,960';
  64. }
  65. if ( not defined $size2d ) {
  66. $size2d = '1024,768';
  67. }
  68. my $xoffset = 'offset -7';
  69. my $yoffset = 'offset -3';
  70. if ( $nooffset == 1 ) {
  71. $xoffset = $EMPTY;
  72. $yoffset = $EMPTY;
  73. }
  74. print <<"_TEXT_";
  75. iozone_visualizer.pl : this script is distributed as public domain
  76. Christian Mautner <christian * mautner . ca>, 2005-10-31
  77. Marc Schoechlin <ms * 256bit.org>, 2007-12-02
  78. Pär Karlsson <feinorgh * gmail . com>, 2012-07-24
  79. _TEXT_
  80. @reports = @ARGV;
  81. if ( not @reports or any { m/^-/msx } @reports ) {
  82. print "usage: $PROGRAM_NAME --3d=x,y -2d=x,y <iozone.out> [<iozone2.out>...]";
  83. exit;
  84. }
  85. if ( any { m{/}msx } @reports ) {
  86. croak 'report files must be in current directory';
  87. }
  88. print
  89. "Configured xtics-offset '$xoffset', configured ytics-offset '$yoffset' (disable with --nooffset)\n";
  90. print 'Size 3d graphs : ' . $size3d . " (modify with '--3d=x,y')\n";
  91. print 'Size 2d graphs : ' . $size2d . " (modify with '--2d=x,y')\n";
  92. #KB reclen write rewrite read reread read write read rewrite read fwrite frewrite fread freread
  93. %columns = (
  94. 'KB' => 1,
  95. 'reclen' => 2,
  96. 'write' => 3,
  97. 'rewrite' => 4,
  98. 'read' => 5,
  99. 'reread' => 6,
  100. 'randread' => 7,
  101. 'randwrite' => 8,
  102. 'bkwdread' => 9,
  103. 'recrewrite' => 10,
  104. 'strideread' => 11,
  105. 'fwrite' => 12,
  106. 'frewrite' => 13,
  107. 'fread' => 14,
  108. 'freread' => 15,
  109. );
  110. #
  111. # create output directory. the name is the concatenation
  112. # of all report file names (minus the file extension, plus
  113. # prefix report_)
  114. #
  115. $outdir = 'report_' . join q{_}, map { m/([^.]+)([.].*)?/msx && $1 } (@reports);
  116. print {*STDERR} "Output directory: $outdir ";
  117. if ( -d $outdir ) {
  118. print {*STDERR} '(removing old directory) ';
  119. system "rm -rf $outdir";
  120. }
  121. mkdir $outdir or croak "cannot make directory $outdir";
  122. print {*STDERR} "done.\nPreparing data files...";
  123. for my $report (@reports) {
  124. open my $fhr, '<', $report or croak "cannot open $report for reading";
  125. $report =~ m/^([^\.]+)/msx;
  126. $datafile = "$1.dat";
  127. push @datafiles, $datafile;
  128. open my $fho3, '>', "$outdir/$datafile"
  129. or croak "cannot open $outdir/$datafile for writing";
  130. open my $fho2, '>', "$outdir/2d-$datafile"
  131. or croak "cannot open $outdir/$datafile for writing";
  132. my @sorted = sort { $columns{$a} <=> $columns{$b} } keys %columns;
  133. print {$fho3} '# ' . join ($SPACE, @sorted) . "\n";
  134. print {$fho2} '# ' . join ($SPACE, @sorted) . "\n";
  135. my $old_x = 0;
  136. while (<$fhr>) {
  137. my $line = $_;
  138. if ( not $line =~ m/^[\s\d]+$/msx ) {
  139. next;
  140. }
  141. @split = split();
  142. if ( @split != 15 ) {
  143. next;
  144. }
  145. if ( $old_x != $split[0] ) {
  146. print {$fho3} "\n";
  147. }
  148. $old_x = $split[0];
  149. print {$fho3} $line;
  150. if ( $split[1] == 16384 or $split[0] == $split[1] ) {
  151. print {$fho2} $line;
  152. }
  153. }
  154. close $fhr or carp $ERRNO;
  155. close $fho3 or carp $ERRNO;
  156. close $fho2 or carp $ERRNO;
  157. }
  158. print {*STDERR} "done.\nGenerating graphs:";
  159. open my $fhtml, '>', "$outdir/index.html"
  160. or carp "cannot open $outdir/index.html for writing";
  161. print {$fhtml} <<'_HTML_';
  162. <?xml version="1.0" encoding="iso-8859-1"?>
  163. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  164. <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
  165. <head>
  166. <title>IOZone Statistics</title>
  167. <STYLE type="text/css">
  168. .headline { font-family: Arial, Helvetica, sans-serif; font-size: 18px; color: 003300 ; font-weight: bold; text-decoration: none}
  169. </STYLE>
  170. </head>
  171. <body>
  172. <a name="top"></a>
  173. <h1>IOZone Statistics</h1>
  174. <table width="100%" summary="iozone stats">
  175. <tr>
  176. <td>
  177. _HTML_
  178. # Generate Menu
  179. print {$fhtml} <<'_HTML_';
  180. <u><b>## Overview</b></u>
  181. <ul>
  182. _HTML_
  183. for my $column ( keys %columns ) {
  184. if ( $column =~ m/KB|reclen/msx ) {
  185. next;
  186. }
  187. print {$fhtml} '<li><b>'
  188. . uc($column)
  189. . '</b> : '
  190. . '<a href="#'
  191. . $column
  192. . "\">3d</a>\n"
  193. . '<a href="#s2d-'
  194. . $column
  195. . "\">2d</a></li>\n";
  196. }
  197. print {$fhtml} "</ul></td></tr>\n";
  198. # Generate 3D plots
  199. for my $column ( keys %columns ) {
  200. if ( $column =~ m/KB|reclen/msx ) {
  201. next;
  202. }
  203. print {*STDERR} " $column";
  204. open my $fhg, '>', "$outdir/$column.do"
  205. or croak "cannot open $outdir/$column.do for writing";
  206. print {$fhg} <<"_GNUPLOT_";
  207. set title "Iozone performance: $column"
  208. set grid lt 2 lw 1
  209. set surface
  210. set xtics $xoffset
  211. set ytics $yoffset
  212. set logscale x 2
  213. set logscale y 2
  214. set autoscale z
  215. set xlabel "File size in Kbytes"
  216. set ylabel "Record size in Kbytes"
  217. set zlabel "Kb/s"
  218. set style data lines
  219. set dgrid3d 80,80,3
  220. set terminal png small size $size3d nocrop
  221. set output "$column.png"
  222. _GNUPLOT_
  223. # original term above:
  224. print {$fhtml} <<"_HTML_";
  225. <tr>
  226. <td align="center">
  227. <h2><a name="$column"></a>3d-$column</h2><a href="#top">[top]</a><BR/>
  228. <img src="$column.png" alt="3d-$column"/><BR/>
  229. </td>
  230. </tr>
  231. _HTML_
  232. print {$fhg} 'splot ' . join q{, },
  233. map { qq{"$_" using 1:2:$columns{$column} title "$_"} } @datafiles;
  234. print {$fhg} "\n";
  235. close $fhg or carp $ERRNO;
  236. open $fhg, '>', "$outdir/2d-$column.do"
  237. or croak "cannot open $outdir/$column.do for writing";
  238. print {$fhg} <<"_GNUPLOT_";
  239. set title "Iozone performance: $column"
  240. #set terminal png small picsize 450 350
  241. set terminal png medium size $size2d nocrop
  242. set logscale x
  243. set xlabel "File size in Kbytes"
  244. set ylabel "Kbytes/sec"
  245. set output "2d-$column.png"
  246. _GNUPLOT_
  247. print {$fhtml} <<"_HTML_";
  248. <tr>
  249. <td align="center">
  250. <h2><a name="s2d-$column"></a>2d-$column</h2><a href="#top">[top]</a><BR/>
  251. <img src="2d-$column.png" alt="2d-$column"/><BR/>
  252. </td>
  253. </tr>
  254. _HTML_
  255. print {$fhg} 'plot ' . join q{, },
  256. map { qq{"2d-$_" using 1:$columns{$column} title "$_" with lines} }
  257. (@datafiles);
  258. print {$fhg} "\n";
  259. close $fhg or carp $ERRNO;
  260. if ( system "cd $outdir && gnuplot $column.do && gnuplot 2d-$column.do" ) {
  261. print {*STDERR} '(failed) ';
  262. }
  263. else {
  264. print {*STDERR} '(ok) ';
  265. }
  266. }
  267. print {$fhtml} <<'_HTML_';
  268. </table>
  269. </body>
  270. </html>
  271. _HTML_
  272. print {*STDERR} "done.\n";