#!/usr/bin/perl -T
# examples/benchmark.pl
# Compare the ISAAC RNG implementations between each other, and between
# other algorithms.
use strict;
use warnings;
eval {
require Benchmark::ProgressBar;
Benchmark::ProgressBar->import('cmpthese');
};
if ($@) {
require Benchmark;
Benchmark->import('cmpthese');
}
=head1 NAME
benchmark.pl - Test performance of various random number generators
=head1 VERSION
Version 1.0
=cut
use version; our $VERSION = qv('1.0');
my $LOOPS = 10_000; # Number of sequences to generate
my $NUMTESTS = 2_500; # Numbers to generate each test
my %TESTING; # modules we're testing
=head1 SYNOPSIS
Usage: benchmark.pl
This script will automatically detect available PRNG algorithms and compare
them using the Benchmark module. It will keep Pure Perl and C/XS modules
separate, so as to compare apples to apples.
=head1 DESCRIPTION
This script currently knows about the following modules, and will compare
them if they are installed.
This module will first compile all of the modules; loading time is also
benchmarked and compared, but separately from the rest of the operation.
For object oriented random number algorithms, the constructor is called
during the benchmark loop, so overhead due to initialization is fairly
counted too.
It will get 5 million integers from each, so as to provide a good sample
size. You can tune this, but you'll have to edit the file.
=head2 ALGORITHMS
=over
=item * Math::Random::ISAAC::PP (Perl)
=item * Math::Random::ISAAC::XS (XS/C)
=item * Math::Random::MT (XS/C)
=item * Math::Random::MT::Perl (Perl)
=item * Math::Random::TT800 (XS/C)
=item * Math::Random::random_uniform_integer (XS/C)
=item * Perl core rand() function
=back
=cut
print "Loading modules, please wait...\n";
load('Math::Random');
load('Math::Random::ISAAC::XS');
load('Math::Random::ISAAC::PP');
load('Math::Random::TT800');
load('Math::Random::MT');
load('Math::Random::MT::Perl');
print 'Setting up C/XS number generators... ';
my $seed = time;
my $code = {};
# Set up all of the modules we've just loaded
$code->{'Core'} = sub {
my $var;
srand($seed);
for (1..$NUMTESTS) {
$var = rand();
}
};
if ($TESTING{'Math::Random'}) {
$code->{'Math::Random'} = sub {
my $var;
Math::Random::random_set_seed($seed, $seed);
for (1..$NUMTESTS) {
$var = Math::Random::random_uniform();
}
};
}
if ($TESTING{'Math::Random::ISAAC::XS'}) {
$code->{'ISAAC::XS'} = sub {
my $rng = Math::Random::ISAAC::XS->new($seed);
my $var;
for (1..$NUMTESTS) {
$var = $rng->irand();
}
};
}
if ($TESTING{'Math::Random::ISAAC::PP'}) {
$code->{'ISAAC::PP'} = sub {
my $rng = Math::Random::ISAAC::PP->new($seed);
my $var;
for (1..$NUMTESTS) {
$var = $rng->irand();
}
};
}
if ($TESTING{'Math::Random::TT800'}) {
$code->{'TT800'} = sub {
my $rng = Math::Random::TT800->new($seed);
my $var;
for (1..$NUMTESTS) {
$var = $rng->next_int();
}
};
}
if ($TESTING{'Math::Random::MT'}) {
$code->{'MT'} = sub {
my $rng = Math::Random::MT->new($seed);
my $var;
for (1..$NUMTESTS) {
$var = $rng->rand();
}
};
}
if ($TESTING{'Math::Random::MT::Perl'}) {
$code->{'MT::Perl'} = sub {
my $rng = Math::Random::MT::Perl->new($seed);
my $var;
for (1..$NUMTESTS) {
$var = $rng->rand();
}
};
}
print "done.\n";
print "Running comparisons (this might take a while)...\n\n";
cmpthese($LOOPS, $code);
sub load {
my ($module) = @_;
print ' ' . $module . '... ';
eval 'use ' . $module;
if ($@) {
print 'not installed.';
$TESTING{$module} = 0;
}
else {
print 'done.';
$TESTING{$module} = 1;
}
print "\n";
return;
}
=head1 AUTHOR
Jonathan Yu E<lt>[email protected]<gt>
=head1 SUPPORT
For support details, please look at C<perldoc Math::Random::ISAAC> and
use the corresponding support methods.
=head1 LICENSE
This has the same copyright and licensing terms as L<Math::Random::ISAAC::XS>.
=head1 SEE ALSO
L<Math::Random::ISAAC::PP>,
L<Math::Random::ISAAC::XS>,
L<Math::Random::MT>,
L<Math::Random::MT::Perl>,
L<Math::Random::TT800>,
L<Math::Random::random_uniform_integer>,
=cut