==== Speed tests ====
As cgi: (from scratch each time):
Rate origCode duff L~R ccn fizbin ccn_fast ccn_faster
origCode 3799/s -- -33% -83% -87% -89% -96% -97%
duff 5671/s 49% -- -75% -80% -84% -94% -95%
L~R 23009/s 506% 306% -- -19% -36% -75% -79%
ccn 28461/s 649% 402% 24% -- -21% -69% -75%
fizbin 36068/s 849% 536% 57% 27% -- -61% -68%
ccn_fast 92559/s 2337% 1532% 302% 225% 157% -- -17%
ccn_faster 111920/s 2846% 1874% 386% 293% 210% 21% --
As mod_perl: (NOT from scratch each time):
Rate fizbin ccn_fast ccn ccn_faster L~R origCode duff
fizbin 36073/s -- -61% -62% -68% -92% -92% -92%
ccn_fast 92123/s 155% -- -2% -17% -80% -80% -80%
ccn 94311/s 161% 2% -- -15% -79% -80% -80%
ccn_faster 111200/s 208% 21% 18% -- -75% -76% -76%
L~R 450572/s 1149% 389% 378% 305% -- -3% -3%
origCode 462599/s 1182% 402% 391% 316% 3% -- -1%
duff 466249/s 1193% 406% 394% 319% 3% 1% --
####
#!perl
use strict;
use Benchmark qw(cmpthese);
my $str = "17:43:33:21:23:19:27:6";
my $setup_codehash = {
origCode => sub {
my @ary;
my %hash = split /:/, $str;
foreach my $k ( keys %hash ) {
push( @ary, map { $hash{$k} } ( 1 .. $k ) );
}
\@ary;
},
ccn => sub {
my %hash = split /:/, $str;
\%hash,
},
"L~R" => sub {
my $lookup;
my %hash = reverse split /:/, $str;
while ( my ( $key, $val ) = each %hash ) {
$lookup .= pack( "C*", ($key) x $val );
}
$lookup;
},
duff => sub {
my @ary;
my @a = split /:/, $str;
@a % 2 && die; # not an even number of items
while ( my ( $p, $ad ) = splice @a, 0, 2 ) {
push @ary, ($ad) x $p;
}
\@ary;
},
};
my $codehash = {
origCode => sub {
my $adId = $_[0]->[ int( rand(100) ) ];
},
ccn => sub {
my $adno;
my $rand = rand 100;
my $sum = 0;
for ( keys %{$_[0]} ) { # there is no need of sorted keys
$adno = $_[0]->{$_};
last if ( $sum += $_ ) > $rand;
}
$adno;
},
"L~R" => sub {
my $addid = unpack( "C", substr( $_[0], rand 100, 1 ) );
},
duff => sub {
my $adId = $_[0]->[ int( rand(100) ) ];
},
fizbin => sub {
my @a = split /:/, $str;
my $r = int( rand(100) );
my ( $adId, $p );
while ( ( $p, $adId ) = splice @a, 0, 2 ) {
if ( $r < $p ) { last; }
$r -= $p;
}
$adId;
},
ccn_fast => sub {
my $rand = rand 100;
my $mystr = $str; # this line is needed for repetitive test only
1 while $mystr =~ /([^:]+):([^:]+):?/g and (($rand -= $1) > 0);
$2;
},
ccn_faster => sub {
my $rand = rand 100;
pos($str)=0; # this line is needed for repetitive test only
1 while $str =~ /([^:]+):([^:]+):?/g and (($rand -= $1) > 0);
$2;
},
};
sub phash (%) {
my %h = @_;
return "{"
. join( ", ",
map { sprintf( '%s => %3.3f', $_, $h{$_} ); }
sort { $a <=> $b } keys(%h) )
. "}";
}
sub make_cgistyle_routine ($) {
my $subname = shift;
if ($setup_codehash->{$subname}) {
return sub {$codehash->{$subname}->($setup_codehash->{$subname}->());};
}
else
{
return sub {$codehash->{$subname}->();};
}
}
sub make_mpstyle_routine ($) {
my $subname = shift;
if ($setup_codehash->{$subname}) {
my @setupvals = $setup_codehash->{$subname}->();
return sub {$codehash->{$subname}->(@setupvals);};
}
else
{
return sub {$codehash->{$subname}->();};
}
}
print "==== Correctness tests ==== \n\n";
my %strhash = reverse split( /:/, $str );
print "Probabilities are: ", phash(%strhash), "\n";
foreach my $subname ( keys %$codehash ) {
my %resultshash = map { $_ => 0 } keys %strhash;
my $routine = make_mpstyle_routine($subname);
do { $resultshash{ $routine->() } += 0.001; }
for ( 1 .. 100000 );
print "$subname yielded ", phash(%resultshash), "\n";
do {
print "$subname failed\n" and last
if ( abs( $resultshash{$_} - $strhash{$_} ) > 0.3 );
}
for keys(%strhash);
}
print "\n==== Speed tests ====\n";
print "\nAs cgi: (from scratch each time):\n";
cmpthese( -5,
{map {$_ => make_cgistyle_routine($_)} keys %$codehash });
print "\nAs mod_perl: (NOT from scratch each time):\n";
cmpthese( -5,
{map {$_ => make_mpstyle_routine($_) } keys %$codehash });
####
--
@/=map{[/./g]}qw/.h_nJ Xapou cets krht ele_ r_ra/;
map{y/X_/\n /;print}map{pop@$_}@/for@/