#! /usr/bin/perl -w # # Make an HTML report to compare the reports from iozone. # # If there are more than three runs for a system, the best and worst # result for each measurement will be thrown away before taking the # average. # # Improvements in performance from system A to system B are colour # coded as green, regressions are red. If the factor is more than 2, # the brightness of the colour is adjusted accordingly. In each cell, # the upper number is A, the bottom number is B. # # Please send comments or improvements to # Kjetil Torgrim Homme # Released into the public domain, 2006 # # Version 1.0 sub usage { print STDERR "Usage: $0 -a report ... -b report ...\n"; exit(64); } my $re_row = '^' . ('\s+(\d+)' x 15); my @data = (); # $data[system 0 eller 1]->[filnummer]->[rad]->[kolonne]; my @filenames = ([], []); my $dataset = 0; my $header; while (@ARGV) { if ($ARGV[0] eq "-a") { $system = 0; $dataset = 0; shift; } elsif ($ARGV[0] eq "-b") { $system = 1; $dataset = 0; shift; } elsif ($ARGV[0] =~ /^-/) { usage(); } else { my $file = shift; push(@{$filenames[$system]}, $file); open(F, $file) || die "$file: $!\n"; $header = slurp_header("F"); $data[$system]->[$dataset] = []; while () { chomp; my @cap; if (@cap = /$re_row/o) { push(@{$data[$system]->[$dataset]}, \@cap); } elsif (/test complete/ || /^\s*$/) { next; } else { print STDERR "Hmm, $file: '$_'\n"; } } close(F); ++$dataset; } } my $set_a = longest_common_prefix(@{$filenames[0]}); my $set_b = longest_common_prefix(@{$filenames[1]}); print <<"_end_"; Iozone: $set_a vs $set_b _end_ print "$header\n"; print_table(); exit(0); # Map ratio between the two values into an RGB value. This is done by # first calculating the colour in HSV. H (hue) goes from red (0 # degrees) to green (135 degrees). Yellow is in the middle. # If the ratio is bigger than $limit, adjust V (value or brightness) # as well. The brightness is reduced by a third of the log10 of the # ratio adjusted by $limit. For $limit == 2, this means brightness is # halved when the factor between the two values is 63. It becomes # black for a factor of 2000, but blacking out such presumed anomalies # is probably a feature, not a bug. sub danger_colour { my ($val_a, $val_b) = @_; my $limit = 2; my $ratio = $val_b / $val_a; if ($ratio < 1) { $ratio = -1 / $ratio; } my $brightness = abs($ratio) > $limit ? 1-log(abs($ratio) / $limit) / log(10) / 3 : 1.0; $ratio = max(min($ratio, $limit), -$limit); my $hue = 135/2 + ($ratio - $ratio/abs($ratio)) * 135/2/$limit; return sprintf("#%02x%02x%02x", hsv_to_rgb($hue/360, 1.0, $brightness)); } sub slurp_header { my ($fh) = @_; my $re_h1 = '^\s+(random)' . ('\s+(\S+)' x 4); my $re_h2 = '^\s+(KB)' . ('\s+(\S+)' x 14); my @headers; my @html= ("
");
    while (<$fh>) {
	chomp;
	my @cap;
	if (@cap = /$re_h1/o) {
 	    @headers = ("", "", "", "", "", "", @cap, "", "", "", "");
	} elsif (@cap = /$re_h2/o) {
	    push(@html, "
\n"); for my $i (0 .. $#headers) { push(@html, " "); } push(@html, " "); last; } else { push(@html, $_); } } return join("\n", @html); } sub print_table { my $num_columns = @{$data[0]->[0]->[0]}; for my $row (0 .. @{$data[0]->[0]}-1) { print " \n"; for my $column (0 .. 1) { printf(" \n", $data[0]->[0]->[$row]->[$column]); } for my $column (2 .. $num_columns-1) { my $val_a = avg_value($data[0], $row, $column); my $val_b = avg_value($data[1], $row, $column); printf(" \n", danger_colour($val_a, $val_b), $val_a, $val_b); } print " \n"; } print "
$headers[$i]
$cap[$i]
%d%d
%d
\n\n"; } sub avg_value { my ($data, $row, $column) = @_; my @values = (); my $sum = 0; for my $dataset (0 .. @{$data}-1) { unshift(@values, $data->[$dataset]->[$row]->[$column]); $sum += $values[0]; } @values = sort {$a <=> $b} @values; if (@values > 3) { $sum -= shift(@values); $sum -= pop(@values); } return $sum / @values; } sub longest_common_prefix { my $prefix = shift; for (@_) { chop($prefix) while (! /^\Q$prefix\E/); } return $prefix; } # code taken from http://www.easyrgb.com/math.php?MATH=M21#text21 sub hsv_to_rgb { my ($h, $s, $v) = @_; my ($r, $g, $b); my ($var_r, $var_g, $var_b); # HSV values = 0 1 if ($s == 0) { $r = $v * 255; $g = $v * 255; $b = $v * 255; } else { my $var_h = $h * 6; if ($var_h == 6) { $var_h = 0; # H must be < 1 } my $var_i = int($var_h); # Or ... var_i = floor( var_h ) my $var_1 = $v * (1 - $s); my $var_2 = $v * (1 - $s * ($var_h - $var_i)); my $var_3 = $v * (1 - $s * (1 - ($var_h - $var_i))); if ($var_i == 0) { $var_r = $v; $var_g = $var_3; $var_b = $var_1; } elsif ($var_i == 1) { $var_r = $var_2; $var_g = $v; $var_b = $var_1; } elsif ($var_i == 2) { $var_r = $var_1; $var_g = $v; $var_b = $var_3; } elsif ($var_i == 3) { $var_r = $var_1; $var_g = $var_2; $var_b = $v; } elsif ($var_i == 4) { $var_r = $var_3; $var_g = $var_1; $var_b = $v; } else { $var_r = $v; $var_g = $var_1; $var_b = $var_2; } $r = $var_r * 255; # RGB results = 0 255 $g = $var_g * 255; $b = $var_b * 255; } return ($r, $g, $b); } sub min { return $_[0] < $_[1] ? $_[0] : $_[1]; } sub max { return $_[0] > $_[1] ? $_[0] : $_[1]; }