#!/usr/bin/perl
# Compares random number generation timings for Perl's core function,
# Math::Random::MT::Auto and Math::Random::MT (if available).
# Usage: timings.pl [--local] [COUNT]
# --local = Don't try internet sources
use strict;
use warnings;
no warnings 'void';
$| = 1;
use Math::Random::MT::Auto qw(rand irand gaussian exponential
srand get_seed set_seed :!auto);
use Time::HiRes;
use Config;
# Warning signal handler
my @WARN;
$SIG{__WARN__} = sub { push(@WARN, @_); };
# Potentially available sources
my %SRCS = (
'/dev/random' => 1,
'win32' => 1,
'random_org' => 1,
'hotbits' => 1,
'rn_info' => 1,
);
# Internet sources
my @INET = qw(random_org hotbits rn_info);
my $DEFAULT_SRC = 'random_org';
MAIN:
{
# Command line arguments
my $count = 3120000;
my $local = 0;
for my $arg (@ARGV) {
if ($arg eq '--local') {
# Local mode - no Internet sources
$local = 1;
} else {
$count = 0 + $arg;
}
}
# Check sources
check_sources($local);
my ($cnt, $start, $end);
print("Random numbers generation timing\n");
print("\n- Core -\n");
# Time Perl's srand()
my $seed = CORE::time() + $$;
$start = Time::HiRes::time();
CORE::srand($seed);
$end = Time::HiRes::time();
printf("srand:\t\t%f secs.\n", $end - $start);
# Loop overhead
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
}
$end = Time::HiRes::time();
my $overhead = $end - $start;
# Time Perl's rand()
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
CORE::rand();
}
$end = Time::HiRes::time();
printf("rand:\t\t%f secs. (%d)\n", ($end-$start)-$overhead, $count);
# Reseed
CORE::srand($seed);
# Time Perl's rand(arg)
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
CORE::rand(5);
}
$end = Time::HiRes::time();
printf("rand(5):\t%f secs. (%d)\n", ($end-$start)-$overhead, $count);
# Time Perl's rand() to product 64-bit randoms
if ($Config{'uvsize'} == 8) {
# Reseed
CORE::srand($seed);
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
(int(CORE::rand(4294967296)) << 32) | int(CORE::rand(4294967296));
}
$end = Time::HiRes::time();
printf("rand [64-bit]:\t%f secs. (%d)\n", ($end-$start)-$overhead, $count);
}
my @seed = @{get_seed()}; # Copy of existing seed
print("\n- Math::Random::MT::Auto - Standalone PRNG -\n");
# Time our srand()
while (my ($src, $available) = each(%SRCS)) {
if ($available) {
$start = Time::HiRes::time();
srand($src, $DEFAULT_SRC);
$end = Time::HiRes::time();
printf("srand:\t\t%f secs. (%s %s)\n", $end - $start, $src, $DEFAULT_SRC);
@seed = @{get_seed()};
}
}
# Time our irand()
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
irand();
}
$end = Time::HiRes::time();
printf("irand:\t\t%f secs. (%d)\n", ($end-$start)-$overhead, $count);
# Reseed
set_seed(\@seed);
# Time our rand()
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
rand();
}
$end = Time::HiRes::time();
printf("rand:\t\t%f secs. (%d)\n", ($end-$start)-$overhead, $count);
# Reseed
set_seed(\@seed);
# Time our rand(arg)
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
rand(5);
}
$end = Time::HiRes::time();
printf("rand(5):\t%f secs. (%d)\n", ($end-$start)-$overhead, $count);
# Reseed
set_seed(\@seed);
# Time gaussian()
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
gaussian();
}
$end = Time::HiRes::time();
printf("gaussian:\t%f secs. (%d)\n", ($end-$start)-$overhead, $count);
# Reseed
set_seed(\@seed);
# Time gaussian(sd, mean)
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
gaussian(3, 69);
}
$end = Time::HiRes::time();
printf("gaussian(3,69):\t%f secs. (%d)\n", ($end-$start)-$overhead, $count);
# Reseed
set_seed(\@seed);
# Time exponential()
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
exponential();
}
$end = Time::HiRes::time();
printf("expon:\t\t%f secs. (%d)\n", ($end-$start)-$overhead, $count);
# Reseed
set_seed(\@seed);
# Time exponential(mean)
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
exponential(5);
}
$end = Time::HiRes::time();
printf("expon(5):\t%f secs. (%d)\n", ($end-$start)-$overhead, $count);
# Reseed
set_seed(\@seed);
print("\n- Math::Random::MT::Auto - OO Interface -\n");
# Time our ->new()
my $rand;
while (my ($src, $available) = each(%SRCS)) {
if ($available) {
$start = Time::HiRes::time();
$rand = Math::Random::MT::Auto->new('SOURCE' => [$src, $DEFAULT_SRC]);
$end = Time::HiRes::time();
printf("new:\t\t%f secs. (%s %s)\n", $end - $start, $src, $DEFAULT_SRC);
}
}
# Reseed
$rand->set_seed(\@seed);
# Time our irand()
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
$rand->irand();
}
$end = Time::HiRes::time();
printf("irand:\t\t%f secs. (%d)\n", ($end-$start)-$overhead, $count);
# Reseed
$rand->set_seed(\@seed);
# Time our rand()
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
$rand->rand();
}
$end = Time::HiRes::time();
printf("rand:\t\t%f secs. (%d)\n", ($end-$start)-$overhead, $count);
# Reseed
$rand->set_seed(\@seed);
# Time our rand(arg)
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
$rand->rand(5);
}
$end = Time::HiRes::time();
printf("rand(5):\t%f secs. (%d)\n", ($end-$start)-$overhead, $count);
# Reseed
$rand->set_seed(\@seed);
# Time our gaussian()
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
$rand->gaussian();
}
$end = Time::HiRes::time();
printf("gaussian:\t%f secs. (%d)\n", ($end-$start)-$overhead, $count);
# Reseed
$rand->set_seed(\@seed);
# Time gaussian(sd, mean)
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
$rand->gaussian(3, 69);
}
$end = Time::HiRes::time();
printf("gaussian(3,69):\t%f secs. (%d)\n", ($end-$start)-$overhead, $count);
# Reseed
$rand->set_seed(\@seed);
# Time our exponential()
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
$rand->exponential();
}
$end = Time::HiRes::time();
printf("expon:\t\t%f secs. (%d)\n", ($end-$start)-$overhead, $count);
# Reseed
$rand->set_seed(\@seed);
# Time exponential(mean)
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
$rand->exponential(5);
}
$end = Time::HiRes::time();
printf("expon(5):\t%f secs. (%d)\n", ($end-$start)-$overhead, $count);
# Reseed
$rand->set_seed(\@seed);
# See if Math::Random::MT is available
eval { require Math::Random::MT;
import Math::Random::MT qw(srand rand);
srand($seed); };
if (! $@) {
print("\n- Math::Random::MT - Functional Interface -\n");
# Time its srand() function
$start = Time::HiRes::time();
$rand = srand($seed);
$end = Time::HiRes::time();
printf("srand:\t\t%f secs.\n", $end - $start);
# Time its rand()
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
rand();
}
$end = Time::HiRes::time();
printf("rand:\t\t%f secs. (%d)\n", ($end-$start)-$overhead, $count);
# Reseed
srand($seed);
# Time its rand(arg)
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
rand(5);
}
$end = Time::HiRes::time();
printf("rand(5):\t%f secs. (%d)\n", ($end-$start)-$overhead, $count);
# Time its rand() to product 64-bit randoms
if ($Config{'uvsize'} == 8) {
# Reseed
$rand = Math::Random::MT->new(@seed);
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
(int(rand(4294967296)) << 32) | int(rand(4294967296));
}
$end = Time::HiRes::time();
printf("rand [64-bit]:\t%f secs. (%d)\n", ($end-$start)-$overhead, $count);
}
print("\n- Math::Random::MT - OO Interface -\n");
# Time its new(@seed) method
$start = Time::HiRes::time();
$rand = Math::Random::MT->new(@seed);
$end = Time::HiRes::time();
printf("new:\t\t%f secs. (+ seed acquisition time)\n", $end - $start);
# Time its rand() method
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
$rand->rand();
}
$end = Time::HiRes::time();
printf("rand:\t\t%f secs. (%d)\n", ($end-$start)-$overhead, $count);
# Reseed
$rand = Math::Random::MT->new(@seed);
# Time its rand(arg) method
$cnt = $count;
$start = Time::HiRes::time();
while ($cnt--) {
$rand->rand(5);
}
$end = Time::HiRes::time();
printf("rand(5):\t%f secs. (%d)\n", ($end-$start)-$overhead, $count);
}
}
exit(0);
### Subroutines ###
sub check_sources
{
my $local = $_[0];
print('Checking seed sources...');
# Check availability of win32 source
eval { srand('win32'); };
if ($@ || @WARN) {
$SRCS{'win32'} = 0;
undef(@WARN);
} else {
$SRCS{'win32'} = 1;
$DEFAULT_SRC = 'win32';
}
# Check availability of /dev/random source
if (-e '/dev/random') {
srand('/dev/random');
if (@WARN) {
$SRCS{'/dev/random'} = 0;
undef(@WARN);
} else {
$SRCS{'/dev/random'} = 1;
$DEFAULT_SRC = '/dev/random';
}
} else {
$SRCS{'/dev/random'} = 0;
}
# Local mode - no Internet sources
if ($local) {
@SRCS{@INET} = 0;
return;
}
# Check for LWP::UserAgent module
eval {
require LWP::UserAgent;
};
if ($@) {
@SRCS{@INET} = 0;
return;
}
# Check availability of Internet sources
for my $src (@INET) {
srand($src, $DEFAULT_SRC);
if (@WARN) {
$SRCS{$src} = 0;
undef(@WARN);
} else {
$SRCS{$src} = 1;
}
}
# Done
print("\n\n");
}
# EOF
syntax highlighted by Code2HTML, v. 0.9.1