| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | #!/usr/bin/perl -w | 
| 2 |  |  |  |  |  |  |  | 
| 3 |  |  |  |  |  |  | # The script calculates primes using Arch::SharedIndex package. | 
| 4 |  |  |  |  |  |  | # It creates multiple processes that all modify the same index. | 
| 5 |  |  |  |  |  |  | # This version uses perl_data serialization and builds lists of divisors. | 
| 6 |  |  |  |  |  |  |  | 
| 7 | 10 |  |  | 10 |  | 7940 | use FindBin qw($Bin); | 
|  | 10 |  |  |  |  | 13420 |  | 
|  | 10 |  |  |  |  | 1540 |  | 
| 8 | 10 |  |  | 10 |  | 8990 | use lib "$Bin/../perllib"; | 
|  | 10 |  |  |  |  | 8930 |  | 
|  | 10 |  |  |  |  | 90 |  | 
| 9 |  |  |  |  |  |  |  | 
| 10 | 10 |  |  |  |  | 50 | my $auto_test = !@ARGV; | 
| 11 | 10 |  | 50 |  |  | 120 | my $max_multiplier = shift || 10; | 
| 12 | 10 |  |  |  |  | 30 | my $max_prime = $max_multiplier * $max_multiplier; | 
| 13 |  |  |  |  |  |  |  | 
| 14 | 10 | 50 |  | 10 |  | 15200 | use Test::More tests => @ARGV? 2: 9; | 
|  | 10 |  |  |  |  | 272770 |  | 
|  | 10 |  |  |  |  | 160 |  | 
| 15 | 10 |  |  | 10 |  | 90 | use_ok("Arch::SharedIndex"); | 
|  | 10 |  |  |  |  | 11250 |  | 
|  | 10 |  |  |  |  | 40 |  | 
|  | 10 |  |  |  |  | 30 |  | 
|  | 10 |  |  |  |  | 330 |  | 
| 16 |  |  |  |  |  |  |  | 
| 17 | 10 |  |  |  |  | 10970 | my $file_name = "/tmp/shared-primes-3-$$"; | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | sub create_shared_index () { | 
| 20 | 19 |  |  | 19 |  | 2988 | return Arch::SharedIndex->new( | 
| 21 |  |  |  |  |  |  | max_size => $max_prime, | 
| 22 |  |  |  |  |  |  | can_create => 1, | 
| 23 |  |  |  |  |  |  | file => $file_name, | 
| 24 |  |  |  |  |  |  | perl_data => 1, | 
| 25 |  |  |  |  |  |  | ); | 
| 26 |  |  |  |  |  |  | } | 
| 27 | 10 |  |  |  |  | 70 | my $shared_index = create_shared_index(); | 
| 28 | 10 |  |  |  |  | 70 | is(ref($shared_index), 'Arch::SharedIndex', "create index to calculate primes"); | 
| 29 |  |  |  |  |  |  |  | 
| 30 |  |  |  |  |  |  | # populate the index with all candidates (value [] means prime, no divisors) | 
| 31 | 10 |  |  |  |  | 5680 | $shared_index->store(map { $_ => [] } 2 .. $max_prime); | 
|  | 990 |  |  |  |  | 1510 |  | 
| 32 |  |  |  |  |  |  |  | 
| 33 | 10 |  |  |  |  | 190 | for (my $num = 2; $num <= $max_multiplier; $num++) { | 
| 34 | 54 |  |  |  |  | 109610 | my $is_parent = fork(); | 
| 35 | 54 | 100 |  |  |  | 3275 | next if $is_parent; | 
| 36 | 9 | 50 |  |  |  | 4670 | die "Can't fork: $!\n" unless defined $is_parent; | 
| 37 |  |  |  |  |  |  |  | 
| 38 |  |  |  |  |  |  | # in child, dismiss all multiples of $num | 
| 39 | 9 |  |  |  |  | 1687 | my %multiples = map { $_ * $num => 1 } 2 .. int($max_prime / $num); | 
|  | 182 |  |  |  |  | 4530 |  | 
| 40 | 9 |  |  |  |  | 992 | $shared_index = create_shared_index();  # recreate for testing only | 
| 41 |  |  |  |  |  |  |  | 
| 42 |  |  |  |  |  |  | # delete all *5 numbers from the index | 
| 43 | 9 | 100 |  |  |  | 1189 | if ($num == 5) { | 
| 44 | 1 |  |  | 50 |  | 186 | $shared_index->filter(sub { $multiples{$_[0]} }); | 
|  | 50 |  |  |  |  | 157 |  | 
| 45 | 1 |  |  |  |  | 251 | exit 0; | 
| 46 |  |  |  |  |  |  | } | 
| 47 |  |  |  |  |  |  | $shared_index->update( | 
| 48 | 8 |  |  | 202 |  | 1556 | sub { [ @{$_[1]}, $num ] }, sub { $multiples{$_[0]} }); | 
|  | 116 |  |  |  |  | 236 |  | 
|  | 116 |  |  |  |  | 728 |  | 
|  | 560 |  |  |  |  | 1864 |  | 
| 49 | 8 |  |  |  |  | 2151 | exit 0; | 
| 50 |  |  |  |  |  |  | } | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | # delete all even numbers from the index | 
| 53 | 1 |  |  |  |  | 130 | $shared_index->delete(map { $_ * 2 } 2 .. int($max_prime / 2)); | 
|  | 49 |  |  |  |  | 140 |  | 
| 54 |  |  |  |  |  |  |  | 
| 55 |  |  |  |  |  |  | # wait for children | 
| 56 | 1 |  |  |  |  | 1292994 | while (wait() > 0) {} | 
| 57 |  |  |  |  |  |  |  | 
| 58 | 1 |  |  |  |  | 35 | my @keys = $shared_index->keys; | 
| 59 | 1 | 100 |  |  |  | 10 | my @values1 = map { @$_? 0: 1 } $shared_index->values; | 
|  | 41 |  |  |  |  | 75 |  | 
| 60 | 1 | 100 |  |  |  | 17 | my @values2 = map { @$_? 0: 1 } $shared_index->fetch(@keys); | 
|  | 41 |  |  |  |  | 301 |  | 
| 61 | 1 |  |  | 41 |  | 112 | my @primes = sort { $a <=> $b } $shared_index->grep(sub { @{$_[1]} == 0 }); | 
|  | 24 |  |  |  |  | 51 |  | 
|  | 41 |  |  |  |  | 44 |  | 
|  | 41 |  |  |  |  | 140 |  | 
| 62 |  |  |  |  |  |  |  | 
| 63 | 1 |  |  |  |  | 9 | my $num_keys = @keys; | 
| 64 | 1 |  |  |  |  | 437 | my $num_values1 = @values1; | 
| 65 | 1 |  |  |  |  | 5 | my $num_values2 = @values2; | 
| 66 | 1 |  |  |  |  | 15 | my $values1_str = join('', @values1); | 
| 67 | 1 |  |  |  |  | 14 | my $values2_str = join('', @values2); | 
| 68 | 1 |  |  |  |  | 3 | my $num_primes = @primes; | 
| 69 | 1 |  |  |  |  | 7 | my $primes_str = join(', ', @primes); | 
| 70 |  |  |  |  |  |  |  | 
| 71 | 1 | 50 |  |  |  | 5 | if ($auto_test) { | 
| 72 | 1 |  |  |  |  | 2 | my $exp_num_keys = 41; | 
| 73 | 1 |  |  |  |  | 3 | my $exp_values_str = "11110111101011010111001011010110101010010"; | 
| 74 | 1 |  |  |  |  | 2 | my $exp_num_primes = 25; | 
| 75 | 1 |  |  |  |  | 8 | my $exp_primes_str = "2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97"; | 
| 76 | 1 |  |  |  |  | 16 | is($num_keys, $exp_num_keys, "verify num_keys (odd non *5 numbers)"); | 
| 77 | 1 |  |  |  |  | 1832 | is($num_values1, $exp_num_keys, "verify number of values (1)"); | 
| 78 | 1 |  |  |  |  | 1029 | is($values1_str, $exp_values_str, "verify values (1)"); | 
| 79 | 1 |  |  |  |  | 941 | is($num_values1, $exp_num_keys, "verify number of values (2)"); | 
| 80 | 1 |  |  |  |  | 1288 | is($values2_str, $exp_values_str, "verify values (2)"); | 
| 81 | 1 |  |  |  |  | 1226 | is($num_primes, $exp_num_primes, "verify number of primes"); | 
| 82 | 1 |  |  |  |  | 1198 | is($primes_str, $exp_primes_str, "verify primes"); | 
| 83 |  |  |  |  |  |  | } else { | 
| 84 | 0 |  |  |  |  | 0 | printf "Number of keys (odd non *5 numbers): %d\n", $num_keys; | 
| 85 | 0 |  |  |  |  | 0 | printf "Values (1-st): %d - %s\n", $num_values1, $values1_str; | 
| 86 | 0 |  |  |  |  | 0 | printf "Values (2-nd): %d - %s\n", $num_values2, $values2_str; | 
| 87 | 0 |  |  |  |  | 0 | printf "Primes: %d - %s\n", $num_primes, $primes_str; | 
| 88 |  |  |  |  |  |  | } | 
| 89 |  |  |  |  |  |  |  | 
| 90 | 1 |  |  |  |  | 2483 | unlink($file_name); |