perl -e 'use Inline C=>q{void greet(){printf("Hello, world\n");}};greet' #### use strict; use warnings; use autodie; use v5.12; use Benchmark qw/cmpthese/; use Test::More tests => 3; use Inline 'C'; use constant TOP => 150000; use constant TIME => 5; is( scalar @{ basic_perl( 3571 ) }, 500, "The first 500 primes are found from 2 to 3571." ); is_deeply( external_cpp(), basic_perl(), "external_cpp() function gives same results as basic_perl()." ); is_deeply( inline_c(), basic_perl(), "inline_c() function gives same results as basic_perl()." ); note "\nComparing basic_perl(), external_cpp(), and inline_c() for\n", TIME, " seconds searching ", TOP, " integers.\n\n"; cmpthese( - TIME, { basic_perl => \&basic_perl, external_cpp => \&external_cpp, inline_c => \&inline_c, }, ); note "\nI love it when a plan comes together.\n\n"; # The pure Perl version. sub basic_perl { my $top = $_[0] // TOP; my @primes = ( 2 ); BASIC_OUTER: for( my $i = 3; $i <= $top; $i += 2 ) { my $sqrt_i = sqrt( $i ); for( my $j = 3; $j <= $sqrt_i; $j += 2 ) { next BASIC_OUTER unless $i % $j; } push @primes, $i; } return \@primes; } # A wrapper around the external executable compiled in C++. sub external_cpp { my $top = TOP; open my $fh, '-|', "primes.exe $top"; chomp( my @primes = <$fh> ); close $fh; return \@primes; } # To be consistent: a wrapper around the Inline C version. sub inline_c{ my $top = TOP; my @primes = inline_c_primes( $top ); return \@primes; } __END__ // Reference only (not used by Inline::C ) // The source code, "primes.cpp" for "primes.exe", // used by external_cpp(). #include #include #include #include #include using namespace std; vector get_primes( int search_to ); void print( int value ); // The first 500 primes are found from 2 to 3571. const int TOP = 3571; // http://en.wikipedia.org/wiki/List_of_prime_numbers int main( int argc, char *argv[] ) { int search_to = ( argc > 1 ) ? atoi(argv[1]) : TOP; vector primes = get_primes( search_to ); for_each( primes.begin(), primes.end(), print ); return 0; } vector get_primes( int search_to ) { vector primes; primes.push_back( 2 ); for( int i = 3; i <= search_to; i += 2 ) { int sqrt_i = sqrt( i ); for( int j = 3; j <= sqrt_i; j += 2 ) { if( i % j == 0 ) goto SKIP; } primes.push_back( i ); SKIP: {}; } return primes; } void print ( int value ) { cout << value << endl; } __C__ # Here is the C code that is compiled by Inline::C #include "math.h" void inline_c_primes( int search_to ) { Inline_Stack_Vars; Inline_Stack_Reset; Inline_Stack_Push(sv_2mortal(newSViv(2))); int i; for( i = 3; i <= search_to; i+=2 ) { int sqrt_i = sqrt( i ); int qualifies = 1; int j; for( j = 3; ( j <= sqrt_i ) && ( qualifies==1 ); j += 2 ) { if( i % j == 0 ) { qualifies = 0; } } if( qualifies == 1 ) { Inline_Stack_Push(sv_2mortal(newSViv(i))); } } Inline_Stack_Done; } # Cross your fingers and hope for the best! #### 1..3 ok 1 - The first 500 primes are found from 2 to 3571. ok 2 - external_cpp() function gives same results as basic_perl(). ok 3 - inline_c() function gives same results as basic_perl(). # # Comparing basic_perl(), external_cpp(), and inline_c() for # 5 seconds searching 150000 integers. # Rate basic_perl external_cpp inline_c basic_perl 1.27/s -- -94% -98% external_cpp 20.0/s 1467% -- -66% inline_c 59.3/s 4555% 197% -- # # I love it when a plan comes together. # #### 1..3 ok 1 - The first 500 primes are found from 2 to 3571. ok 2 - external_cpp() function gives same results as basic_perl(). ok 3 - inline_c() function gives same results as basic_perl(). # # Comparing basic_perl(), external_cpp(), and inline_c() for # 5 seconds searching 150000 integers. # Rate basic_perl external_cpp inline_c basic_perl 2.37/s -- -91% -97% external_cpp 25.3/s 969% -- -67% inline_c 76.0/s 3106% 200% -- # # I love it when a plan comes together. # #### use strict; use warnings; use autodie; use v5.12; use Benchmark qw/cmpthese/; use Test::More tests => 4; use Inline 'C' => 'DATA'; use constant TOP => 200000; use constant TIME => 10; note "Operating system: $^O, Perl version: $^V\n\n"; note "Constant TOP is ", TOP; note "Constant TIME is ", TIME, "\n\n"; is( scalar @{ basic_perl( 3571 ) }, 500, "basic_perl(3571): The first 500 primes are found from 2 to 3571." ); is_deeply( external_cpp(TOP), basic_perl(TOP), "external_cpp(TOP): Same results as basic_perl(TOP)." ); is_deeply( inline_c_list(TOP), basic_perl(TOP), "inline_c_list(TOP): Same results as basic_perl(TOP)." ); is_deeply( inline_c_aref(TOP), basic_perl(TOP), "inline_c_aref(TOP): Same result as basic_perl(TOP)." ); note "\nComparing basic_perl(), external_cpp(), inline_c_list(), inline_c_aref()\n", "for ", TIME, " seconds searching ", TOP, " integers.\n\n"; cmpthese( - TIME, { basic_perl => \&basic_perl, external_cpp => \&external_cpp, inline_c_list => \&inline_c_list, inline_c_aref => \&inline_c_aref, }, ); note "\nI love it when a plan comes together.\n\n"; # The pure Perl version. sub basic_perl { my $top = $_[0] // TOP; my @primes = ( 2 ); BASIC_OUTER: for( my $i = 3; $i <= $top; $i += 2 ) { my $sqrt_i = sqrt( $i ); for( my $j = 3; $j <= $sqrt_i ; $j += 2 ) { next BASIC_OUTER unless $i % $j; } push @primes, $i; } return \@primes; } # A wrapper around the external executable compiled in C++. sub external_cpp { my $top = $_[0] // TOP; open my $fh, '-|', "primes $top"; chomp( my @primes = <$fh> ); close $fh; return \@primes; } # To be consistent: a wrapper around the Inline C version. sub inline_c_list{ my $top = $_[0] // TOP; my @primes = inline_c_list_primes( $top ); return \@primes; } sub inline_c_aref{ my $top = $_[0] // TOP; return inline_c_aref_primes( $top ); } __END__ // Reference only (not used by Inline::C ) // The source code, "primes.cpp" for "primes.exe", // used by external_cpp(). #include #include #include #include #include using namespace std; vector get_primes( int search_to ); void print( int value ); // The first 500 primes are found from 2 to 3571. const int TOP = 3571; // http://en.wikipedia.org/wiki/List_of_prime_numbers int main(int argc, char *argv[] ) { int search_to = ( argc > 1 ) ? atoi(argv[1]) : TOP; vector primes = get_primes( search_to ); for_each( primes.begin(), primes.end(), print ); return 0; } vector get_primes( int search_to ) { vector primes; primes.push_back(2); for( int i = 3; i <= search_to; i += 2 ) { int sqrt_i = sqrt( i ); for( int j = 3; j <= sqrt_i; j += 2 ) { if( i % j == 0 ) goto SKIP; } primes.push_back(i); SKIP: {}; } return primes; } void print ( int value ) { cout << value << endl; } __C__ #include "math.h" void inline_c_list_primes( int search_to ) { Inline_Stack_Vars; Inline_Stack_Reset; Inline_Stack_Push(sv_2mortal(newSViv(2))); int i; for( i = 3; i <= search_to; i+=2 ) { int sqrt_i = sqrt( i ); int qualifies = 1; int j; for( j = 3; (j<=sqrt_i) && (qualifies==1); j += 2 ) { if( i % j == 0 ) { qualifies = 0; } } if( qualifies == 1 ) { Inline_Stack_Push(sv_2mortal(newSViv(i))); } } Inline_Stack_Done; } AV * inline_c_aref_primes ( int search_to ) { AV* av; av = newAV(); av_push( av, newSViv( 2 ) ); int i; for( i = 3; i <= search_to; i+=2 ) { int sqrt_i = sqrt( i ); int qualifies = 1; int j; for( j = 3; (j<=sqrt_i) && (qualifies==1); j += 2 ) { if( i % j == 0 ) { qualifies = 0; } } if( qualifies == 1 ) { av_push( av, newSViv( i ) ); } } return sv_2mortal( av ); } #### 1..4 # Operating system: linux, Perl version: v5.14.2 # # Constant TOP is 200000 # Constant TIME is 10 # ok 1 - basic_perl(3571): The first 500 primes are found from 2 to 3571. ok 2 - external_cpp(TOP): Same results as basic_perl(TOP). ok 3 - inline_c_list(TOP): Same results as basic_perl(TOP). ok 4 - inline_c_aref(TOP): Same result as basic_perl(TOP). # # Comparing basic_perl(), external_cpp(), inline_c_list(), inline_c_aref() # for 10 seconds searching 200000 integers. # Rate basic_perl external_cpp inline_c_list inline_c_aref basic_perl 1.64/s -- -91% -97% -97% external_cpp 17.6/s 977% -- -67% -67% inline_c_list 53.0/s 3138% 201% -- -2% inline_c_aref 54.1/s 3202% 207% 2% -- # # I love it when a plan comes together. #