#!/usr/bin/env perl
use lib qw(bench/lib);
use strict;
use warnings;
use Data::Dumper;
$ENV{EVENT_SEND_COUNT} = 500000 unless exists $ENV{EVENT_SEND_COUNT};
$ENV{MIN_TEST_TIME} = 60 unless exists $ENV{MIN_TEST_TIME};
$ENV{BENCH_DIR} = 'bench' unless exists $ENV{BENCH_DIR};
logger("Configuration: $ENV{EVENT_SEND_COUNT} events and $ENV{MIN_TEST_TIME} seconds minimum test time\n");
my @results = doTests();
my $error = shift(@results);
doLog(@results);
exit($error);
exit(0);
sub logger {
print STDERR @_;
}
sub genFiles {
my ($dir) = @_;
my $dh;
my @paths;
die "$dir is not a directory or is not accessable" unless -d $dir;
die "Could not opendir($dir): $!" unless opendir($dh, $dir);
foreach(readdir($dh)) {
next if m/^\./;
next if -d $_;
push(@paths, "$dir/$_");
}
die "Could not closedir($dir): $!" unless closedir($dh);
return @paths;
}
sub genTests {
my @files;
my @buf;
if (scalar(@ARGV) > 0) {
@files = @ARGV;
} else {
logger("Loading benchmarks from $ENV{BENCH_DIR}/... ");
@files = genFiles($ENV{BENCH_DIR});
logger("found ", scalar(@files), " files\n");
}
foreach(@files) {
my %test = ( file => $_ );
logger("loading $_... ");
$test{cb} = require $_;
logger("done\n");
push(@buf, \%test);
}
return @buf;
}
sub randomInt {
return int(rand(10));
}
sub genData {
my @buf = @_;
logger("Generating test data... ");
foreach(1 .. $ENV{EVENT_SEND_COUNT}) {
push(@buf, [ randomInt(), randomInt() ]);
}
logger("done\n");
return @buf;
}
sub sumData {
my $sum = 0;
foreach(@_) {
$sum += $_->[0] + $_->[1];
}
return $sum;
}
sub doTests {
my @tests = genTests();
my @testData = genData();
my $sum = sumData(@testData);
my $error = 0;
foreach(@tests) {
my $seconds = 0;
my $eventCount = 0;
my $iterations = 0;
logger("Measuring $_->{file}... ");
while(1) {
my ($results, $bench);
$iterations++;
$results = $_->{cb}(@testData);
$bench = $results->{bench};
if ($results->{sum} != $sum) {
logger("INVALID SUM $results->{sum} != $sum ");
$error = 1;
}
$seconds += $bench->[0];
$eventCount += $ENV{EVENT_SEND_COUNT};
if ($seconds >= $ENV{MIN_TEST_TIME}) {
last;
}
logger("$iterations ");
}
$_->{analysis} = {
cpuTime => $seconds,
eventCount => $eventCount,
eventsPerSecond => $eventCount / $seconds,
};
logger("done\n");
}
return ($error, @tests);
}
sub doLog {
my (@tests) = @_;
logger("Report format: file\tevents per second\tcost of solution\n");
foreach(sort({ $b->{analysis}->{eventsPerSecond} <=> $a->{analysis}->{eventsPerSecond} } @tests)) {
my $analysis = $_->{analysis};
my $eventsPerSecond = int($analysis->{eventsPerSecond});
our $fastest;
my $cost;
if (! defined($fastest)) {
$fastest = $eventsPerSecond;
}
$cost = $fastest / $eventsPerSecond;
print "$_->{file}\t$eventsPerSecond\t$cost\n";
}
}