|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #!/usr/bin/perl -w  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # The script calculates primes using Arch::SharedCache package.  | 
| 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # It creates multiple processes that all modify the same cache.  | 
| 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # This version uses perl_data serialization and builds lists of divisors.  | 
| 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
7
 | 
10
 | 
 
 | 
 
 | 
  
10
  
 | 
 
 | 
8720
 | 
 use FindBin qw($Bin);  | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14160
 | 
    | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1420
 | 
    | 
| 
8
 | 
10
 | 
 
 | 
 
 | 
  
10
  
 | 
 
 | 
8200
 | 
 use lib "$Bin/../perllib";  | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12970
 | 
    | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
70
 | 
    | 
| 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
10
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
40
 | 
 my $auto_test = !@ARGV;  | 
| 
11
 | 
10
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
100
 | 
 my $max_multiplier = shift || 10;  | 
| 
12
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
 my $max_prime = $max_multiplier * $max_multiplier;  | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
14
 | 
10
 | 
  
 50
  
 | 
 
 | 
  
10
  
 | 
 
 | 
14340
 | 
 use Test::More tests => @ARGV? 2: 9;  | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
226240
 | 
    | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
170
 | 
    | 
| 
15
 | 
10
 | 
 
 | 
 
 | 
  
10
  
 | 
 
 | 
70
 | 
 use_ok("Arch::SharedCache");  | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10680
 | 
    | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
40
 | 
    | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
    | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
270
 | 
    | 
| 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
17
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11670
 | 
 my $dir_name = "/tmp/shared-primes-4-$$";  | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub create_shared_index () {  | 
| 
20
 | 
19
 | 
 
 | 
 
 | 
  
19
  
 | 
 
 | 
1361
 | 
 	return Arch::SharedCache->new(  | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		max_size => $max_prime,  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		can_create => 1,  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		dir => $dir_name,  | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		perl_data => 1,  | 
| 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	);  | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
27
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
70
 | 
 my $shared_index = create_shared_index();  | 
| 
28
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
80
 | 
 is(ref($shared_index), 'Arch::SharedCache', "create cache to calculate primes");  | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # populate the index with all candidates (value [] means prime, no divisors)  | 
| 
31
 | 
10
 | 
 
 | 
 
 | 
  
990
  
 | 
 
 | 
9970
 | 
 my @values = $shared_index->fetch_store(sub { [] }, 2 .. $max_prime);  | 
| 
 
 | 
990
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3210
 | 
    | 
| 
32
 | 
10
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
490
 | 
 die "Internal error #1 in fetch_store\n" if grep { !$_ || @$_ != 0 } @values;  | 
| 
 
 | 
990
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
3140
 | 
    | 
| 
33
 | 
10
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
150
 | 
 @values = $shared_index->fetch_store(sub { [ 9 ] }, 2 .. $max_prime);  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
34
 | 
10
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
190
 | 
 die "Internal error #2 in fetch_store\n" if grep { !$_ || @$_ != 0 } @values;  | 
| 
 
 | 
990
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
3710
 | 
    | 
| 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
36
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
70
 | 
 for (my $num = 2; $num <= $max_multiplier; $num++) {  | 
| 
37
 | 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
176894
 | 
 	my $is_parent = fork();  | 
| 
38
 | 
54
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
3670
 | 
 	next if $is_parent;  | 
| 
39
 | 
9
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
2327
 | 
 	die "Can't fork: $!\n" unless defined $is_parent;  | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# in child, dismiss all multiples of $num  | 
| 
42
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1145
 | 
 	my %multiples = map { $_ * $num => 1 } 2 .. int($max_prime / $num);  | 
| 
 
 | 
182
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2918
 | 
    | 
| 
43
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
475
 | 
 	$shared_index = create_shared_index();  # recreate for testing only  | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# delete all *5 numbers from the index  | 
| 
46
 | 
9
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1170
 | 
 	if ($num == 5) {  | 
| 
47
 | 
1
 | 
 
 | 
 
 | 
  
50
  
 | 
 
 | 
79
 | 
 		$shared_index->filter(sub { $multiples{$_[0]} });  | 
| 
 
 | 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
219
 | 
    | 
| 
48
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
254
 | 
 		exit 0;  | 
| 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$shared_index->update(  | 
| 
51
 | 
8
 | 
 
 | 
 
 | 
  
192
  
 | 
 
 | 
900
 | 
 		sub { [ @{$_[1]}, $num ] }, sub { $multiples{$_[0]} });  | 
| 
 
 | 
97
 | 
 
 | 
 
 | 
 
 | 
 
 | 
271
 | 
    | 
| 
 
 | 
97
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1184
 | 
    | 
| 
 
 | 
489
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4541
 | 
    | 
| 
52
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7474
 | 
 	exit 0;  | 
| 
53
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # delete all even numbers from the index  | 
| 
56
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
129
 | 
 $shared_index->delete(map { $_ * 2 } 2 .. int($max_prime / 2));  | 
| 
 
 | 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
222
 | 
    | 
| 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # wait for children  | 
| 
59
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2185808
 | 
 while (wait() > 0) {}  | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
61
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
36
 | 
 my @keys = $shared_index->keys;  | 
| 
62
 | 
1
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
20
 | 
 my @values1 = map { @$_? 0: 1 } $shared_index->values;  | 
| 
 
 | 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
84
 | 
    | 
| 
63
 | 
1
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
21
 | 
 my @values2 = map { @$_? 0: 1 } $shared_index->fetch(@keys);  | 
| 
 
 | 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
60
 | 
    | 
| 
64
 | 
1
 | 
 
 | 
 
 | 
  
41
  
 | 
 
 | 
33
 | 
 my @primes = sort { $a <=> $b } $shared_index->grep(sub { @{$_[1]} == 0 });  | 
| 
 
 | 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
36
 | 
    | 
| 
 
 | 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
81
 | 
    | 
| 
 
 | 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
166
 | 
    | 
| 
65
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
66
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
 my $num_keys = @keys;  | 
| 
67
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 my $num_values1 = @values1;  | 
| 
68
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 my $num_values2 = @values2;  | 
| 
69
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
 my $values1_str = join('', @values1);  | 
| 
70
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
 my $values2_str = join('', @values2);  | 
| 
71
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 my $num_primes = @primes;  | 
| 
72
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
 my $primes_str = join(', ', @primes);  | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
74
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
22
 | 
 if ($auto_test) {  | 
| 
75
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 	my $exp_num_keys = 41;  | 
| 
76
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
 	my $exp_values_str = "11110111101011010111001011010110101010010";  | 
| 
77
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 	my $exp_num_primes = 25;  | 
| 
78
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 	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";  | 
| 
79
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
 	is($num_keys, $exp_num_keys, "verify num_keys (odd non *5 numbers)");  | 
| 
80
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1098
 | 
 	is($num_values1, $exp_num_keys, "verify number of values (1)");  | 
| 
81
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
472
 | 
 	is($values1_str, $exp_values_str, "verify values (1)");  | 
| 
82
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
514
 | 
 	is($num_values1, $exp_num_keys, "verify number of values (2)");  | 
| 
83
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
404
 | 
 	is($values2_str, $exp_values_str, "verify values (2)");  | 
| 
84
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
455
 | 
 	is($num_primes, $exp_num_primes, "verify number of primes");  | 
| 
85
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
406
 | 
 	is($primes_str, $exp_primes_str, "verify primes");  | 
| 
86
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 } else {  | 
| 
87
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	printf "Number of keys (odd non *5 numbers): %d\n", $num_keys;  | 
| 
88
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	printf "Values (1-st): %d - %s\n", $num_values1, $values1_str;  | 
| 
89
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	printf "Values (2-nd): %d - %s\n", $num_values2, $values2_str;  | 
| 
90
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	printf "Primes: %d - %s\n", $num_primes, $primes_str;  | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
92
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
93
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16722
 | 
 system("/bin/rm -rf '$dir_name'");  |