sub count_in_hash {
my $num_ints = $_[0] // $datasize;
my %container;
$container{ rand_ranged_value( 1, 999 ) }++
for( 1 .. $num_ints );
return \%container;
}
####
sub count_in_array {
my $num_ints = $_[0] // $datasize;
my @container;
$container[ rand_ranged_value( 1, 999 ) ]++
for( 1 .. $num_ints );
return { # Anonymous hash constructor.
map{
$container[$_] > 0
? ( $_ => $container[$_] )
: ()
} 1 .. $#container
};
}
##
##
int rand_ranged_value ( int min, int max )
{
return ( rand() % ( max - min + 1 ) + min );
}
// Accepts smallest and largest bucket, and number of ints
// to test/produce.
// Returns (on the stack) a list of int/count pairs (pull
// into a hash).
void ints_per_bucket (
int min_bucket,
int max_bucket,
int quantity_ints
)
{
int range_size = max_bucket + 1;
int* int_sieve;
int i;
Newxz( int_sieve, range_size, int );
if( !int_sieve )
croak(
"ints_per_bucket: Couldn't allocate memory.\n"
);
for( i = 0; i < quantity_ints; i++ )
int_sieve[ rand_ranged_value(min_bucket,max_bucket) ]++;
Inline_Stack_Vars;
Inline_Stack_Reset;
for( i = 0; i < range_size; i++ )
if( int_sieve[i] > 0 )
{
// Key ( integer value counted ).
Inline_Stack_Push(
sv_2mortal( newSViv( i ) )
);
// Value ( count for integer value ).
Inline_Stack_Push(
sv_2mortal( newSViv( int_sieve[i] ) )
);
}
Safefree( int_sieve );
Inline_Stack_Done;
}
##
##
#!/usr/bin/env perl
use strict;
use warnings;
use Benchmark qw/ cmpthese /;
use List::Util qw/ max min /;
use Test::More;
use Readonly;
use Inline C => 'DATA';
Readonly my $datasize => 100_000_000;
Readonly my $test_size => 500_000;
my %test_subs = (
array_count => \&count_in_array,
hash_count => \&count_in_hash,
c_aray_cnt => \&count_in_array_c,
);
while ( my( $name, $sref ) = each %test_subs ) {
my $result = $sref->( $test_size );
is( scalar keys %{$result}, 999,
"$name(): Correct key count in RV."
);
is( scalar values %{$result}, 999,
"$name(): Correct value count in RV."
);
is( max( keys %{$result} ), 999,
"$name(): max integer in range."
);
is( min( keys %{$result} ), 1,
"$name(): min integer in range."
);
}
done_testing();
cmpthese( 5, \%test_subs );
sub count_in_array {
my $num_ints = $_[0] // $datasize;
my @container;
$container[ rand_ranged_value( 1, 999 ) ]++
for( 1 .. $num_ints );
return { # Anonymous hash constructor.
map{
$container[$_] > 0
? ( $_ => $container[$_] )
: ()
} 1 .. $#container
};
}
sub count_in_hash {
my $num_ints = $_[0] // $datasize;
my %container;
$container{ rand_ranged_value( 1, 999 ) }++
for( 1 .. $num_ints );
return \%container;
}
sub count_in_array_c {
my $num_ints = $_[0] // $datasize;
return { ints_per_bucket( 1, 999, $num_ints ) };
}
__DATA__
__C__
// Public functions:
void ints_per_bucket (
int min_bucket, int max_bucket, int quantity_ints
);
int rand_ranged_value ( int min, int max );
int rand_ranged_value ( int min, int max )
{
return ( rand() % ( max - min + 1 ) + min );
}
// Accepts smallest and largest bucket, and number of ints
//to test/produce.
// Returns (on the stack) a list of int/count pairs (pull
//into a hash).
void ints_per_bucket (
int min_bucket,
int max_bucket,
int quantity_ints
)
{
int range_size = max_bucket + 1;
int* int_sieve;
int i;
Newxz( int_sieve, range_size, int );
if( !int_sieve )
croak(
"ints_per_bucket: Couldn't allocate memory.\n"
);
for( i = 0; i < quantity_ints; i++ )
int_sieve[ rand_ranged_value(min_bucket,max_bucket) ]++;
Inline_Stack_Vars;
Inline_Stack_Reset;
for( i = 0; i < range_size; i++ )
if( int_sieve[i] > 0 )
{
// Key ( integer value counted ).
Inline_Stack_Push(
sv_2mortal( newSViv( i ) )
);
// Value ( count for integer value ).
Inline_Stack_Push(
sv_2mortal( newSViv( int_sieve[i] ) )
);
}
Safefree( int_sieve );
Inline_Stack_Done;
}
##
##
ok 1 - hash_count(): Correct key count in RV.
ok 2 - hash_count(): Correct value count in RV.
ok 3 - hash_count(): max integer in range.
ok 4 - hash_count(): min integer in range.
ok 5 - array_count(): Correct key count in RV.
ok 6 - array_count(): Correct value count in RV.
ok 7 - array_count(): max integer in range.
ok 8 - array_count(): min integer in range.
ok 9 - c_aray_cnt(): Correct key count in RV.
ok 10 - c_aray_cnt(): Correct value count in RV.
ok 11 - c_aray_cnt(): max integer in range.
ok 12 - c_aray_cnt(): min integer in range.
1..12
s/iter hash_count array_count c_aray_cnt
hash_count 22.8 -- -45% -92%
array_count 12.4 83% -- -85%
c_aray_cnt 1.91 1093% 551% --