Skip to content

Commit

Permalink
created benchmark suite for object delivery and consumption
Browse files Browse the repository at this point in the history
  • Loading branch information
Tyler Riddle committed Aug 18, 2012
1 parent acf08fa commit 5b3c101
Show file tree
Hide file tree
Showing 7 changed files with 355 additions and 0 deletions.
169 changes: 169 additions & 0 deletions bench.pl
@@ -0,0 +1,169 @@
#!/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";
}
}

13 changes: 13 additions & 0 deletions bench/lib/EventBench/Reflex/Event.pm
@@ -0,0 +1,13 @@
package EventBench::Reflex::Event;

use Moose;
use Reflex;

extends 'Reflex::Event';

has arg1 => ( is => 'ro', isa => 'Num', required => 1 );
has arg2 => ( is => 'ro', isa => 'Num', required => 1 );

__PACKAGE__->meta->make_immutable;

1;
27 changes: 27 additions & 0 deletions bench/method-array.pl
@@ -0,0 +1,27 @@
package EventBench::Method::Array;

use strict;
use warnings;
use Benchmark ':hireswallclock';

sub receive_event {
my ($arg1, $arg2) = @_;
our($sum);

$sum += $arg1 + $arg2;
}

return sub {
my (@testData) = @_;
our $sum = 0;
my $bench;

$bench = timeit(1, sub {

foreach(@testData) {
receive_event($_->[0], $_->[1]);
}
});

return { bench => $bench, sum => $sum };
};
26 changes: 26 additions & 0 deletions bench/method-hash.pl
@@ -0,0 +1,26 @@
package EventBench::Method::Hash;

use strict;
use warnings;
use Benchmark ':hireswallclock';

sub receive_event {
my (%event) = @_;
our $sum;

$sum += $event{arg1} + $event{arg2};
}

return sub {
my (@testData) = @_;
our $sum = 0;
my $bench;

$bench = timeit(1, sub {
foreach(@testData) {
receive_event(arg1 => $_->[0], arg2 => $_->[1]);
}
});

return { bench => $bench, sum => $sum };
};
32 changes: 32 additions & 0 deletions bench/objectmethod-array.pm
@@ -0,0 +1,32 @@
package EventBench::ObjectMethod::Array;

use strict;
use warnings;
use Benchmark ':hireswallclock';

sub new {
return bless({}, $_[0]);
}

sub receive_event {
my ($self, $arg1, $arg2) = @_;
our $sum;

$sum += $arg1 + $arg2;
}

return sub {
my (@testData) = @_;
my $test = EventBench::ObjectMethod::Array->new;
our $sum = 0;
my $bench;

$bench = timeit(1, sub {

foreach(@testData) {
$test->receive_event($_->[0], $_->[1]);
}
});

return { bench => $bench, sum => $sum };
};
57 changes: 57 additions & 0 deletions bench/objectmethod-cbmanager.pm
@@ -0,0 +1,57 @@
package EventBench::ObjectMethod::CBManager;

use strict;
use warnings;
use Benchmark ':hireswallclock';
use Scalar::Util qw(weaken);

sub new {
my $self = bless({ }, $_[0]);
our $sum;

$self->{handlers}->{sum} = $self->weakcb(sub {
my ($self, %event) = @_;

$sum += $event{arg1} + $event{arg2};
});

return $self;
}

sub receive_event {
my ($self, %event) = @_;

$self->{handlers}->{$event{name}}->($self, %event);
}

#pass in code ref or method name as string
sub weakcb {
my ($self, $cb) = @_;

weaken($self);

return sub {
my ($self) = shift(@_);

die "expected weak reference to self to be valid but it was undefined" unless defined $self;

return $self->$cb(@_);
};
}

return sub {
my (@testData) = @_;
my $test = EventBench::ObjectMethod::CBManager->new;
my $bench;
our $sum;

$bench = timeit(1, sub {
our $sum = 0;

foreach(@testData) {
$test->receive_event(name => 'sum', arg1 => $_->[0], arg2 => $_->[1]);
}
});

return { bench => $bench, sum => $sum };
};
31 changes: 31 additions & 0 deletions bench/objectmethod-hash.pm
@@ -0,0 +1,31 @@
package EventBench::ObjectMethod::Hash;

use strict;
use warnings;
use Benchmark ':hireswallclock';

sub new {
return bless({}, $_[0]);
}

sub receive_event {
my ($self, %event) = @_;
our $sum;

$sum += $event{arg1} + $event{arg2};
}

return sub {
my (@testData) = @_;
my $test = EventBench::ObjectMethod::Hash->new;
our $sum = 0;
my $bench;

$bench = timeit(1, sub {
foreach(@testData) {
$test->receive_event(arg1 => $_->[0], arg2 => $_->[1]);
}
});

return { bench => $bench, sum => $sum };
};

0 comments on commit 5b3c101

Please sign in to comment.