#!/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; }