#!/usr/bin/perl use File::Temp (); package row; use Moose; has 'exp' => ( is => 'ro', 'isa' => 'Num' ); has 'gen' => ( is => 'ro', 'isa' => 'Num' ); has 'temp' => ( is => 'ro', 'isa' => 'Num' ); has 'update' => ( is => 'ro', 'isa' => 'Num' ); has 'withdraw' => ( is => 'ro', 'isa' => 'Num' ); sub reduce { my $self = shift; my $N = 1 << $self->exp; return row->new( exp => $self->exp, gen => $self->gen / $N, temp => $self->temp / $N, update => $self->update / $N, withdraw => $self->withdraw / $N ); } sub dump { my ($self, $fh) = @_; print $fh join ",", $self->exp, $self->gen, $self->temp, $self->update, $self->withdraw; print $fh "\n"; } package results; use Moose; has 'name' => ( is => 'ro', isa => 'Str', required => 1, ); has 'date' => ( is => 'ro', isa => 'Str', required => 1, ); has 'reduced' => ( is => 'ro', isa => 'Bool', default => 0, ); has 'rows' => ( is => 'ro', isa => 'ArrayRef[row]', default => sub { [] }, ); has 'stub' => ( is => 'ro', isa => 'Str', lazy => 1, builder => '_build_stub', ); sub _build_stub { my $self = shift; my $date = $self->date; my $name = $self->name; my $reduced = "-reduced" if $self->reduced; my $stub = $date . "-" . $name . $reduced; $stub =~ tr/a-zA-Z0-9_-/@/c; return $stub; } sub add { my $self = shift; push @{$self->rows}, row->new(@_); } sub reduce { my $self = shift; return $self if $self->reduced; return results->new( name => $self->name, date => $self->date, reduced => 1, rows => [ map { $_->reduce } @{$self->rows} ], ); } sub dump { my $self = shift; my $fn = $self->stub . ".csv"; open my $CSV, ">", $fn; map { $_->dump($CSV); } @{$self->rows}; close $CSV; return $fn; } sub draw { my $self = shift; my $csv = $self->dump(); my $svg = $self->stub . ".svg"; my $title = $self->name; $title =~ s/_/ /g; open PLOT, "|-", "gnuplot -p"; print PLOT "set terminal svg;\n"; print PLOT "set output '$svg';\n"; print PLOT "set title '$title';\n"; print PLOT "set datafile separator ',';\n"; print PLOT "set jitter over 0.3 spread 0.3;\n"; print PLOT "plot '$csv' using 1:2 title 'gen', '$csv' using 1:3 title 'temp', '$csv' using 1:4 title 'update', '$csv' using 1:5 title 'withdraw';\n"; close PLOT; } package main; my %results; my @done; while (<>) { if (m/(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}).*?Perf (.+) starting$/) { my $date = $1; my $name = $2; die "Garbled input data" if exists $results{$name}; $results{$name} = results->new(name => $name, date => $date); next; } if (m/Perf (.+) done with exp=(\d+)$/) { my $name = $1; die "Garbled input data" unless exists $results{$name}; push @done, $results{$name}; delete $results{$name}; next; } my ($name, $exp, $gen, $temp, $update, $withdraw) = m/Perf (.+) exp=(\d+) times: gen=(\d+) temp=(\d+) update=(\d+) withdraw=(\d+)$/ or next; exists $results{$name} or die "Garbled input data"; $results{$name}->add(exp => $exp, gen => $gen, temp => $temp, update => $update, withdraw => $withdraw); } scalar %results and die "Incomplete input data"; foreach my $res (@done) { $res->reduce->draw(); }