/
ch-2.p6
executable file
·108 lines (91 loc) · 2.23 KB
/
ch-2.p6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#!/usr/bin/env raku
my ($GET_CMD,$SET_CMD,$SYNC_CMD,$UPDATE_CMD,$DUMP_CMD)=0..4;
put "Inital backing store contents:";
largeSlowStore($DUMP_CMD);
my $counter=0;
for ^20 {
put "\nOperation: $counter";
fastSmallCache(($SET_CMD+1).rand.Int,index=>20.rand.Int, value=>100.rand.Int);
fastSmallCache($DUMP_CMD);
put '=' x 20;
$counter++;
}
put "Resulting backing store before flush/sync of lru cache";
largeSlowStore($DUMP_CMD);
fastSmallCache($SYNC_CMD);
put "Resulting backing store after sync ";
largeSlowStore($DUMP_CMD);
sub fastSmallCache($cmd,:$index,:$value){
state $capacity=5;
state %index;
state @lru;
do {
given $cmd {
when $GET_CMD {
put "\nRead Cache: ";
do { given %index{$index} {
when Any {
put "-Miss";
#cache miss
my $val=largeSlowStore($GET_CMD,:$index);
fastSmallCache($UPDATE_CMD,:$index,value=>$val) if defined $val;
}
default {
#cache hit
put "-Hit";
fastSmallCache($UPDATE_CMD,:$index,value=>$_);
}
}
}
}
when ($SET_CMD) {
put "\nWrite cache: ";
fastSmallCache($UPDATE_CMD,:$index,:$value);
}
when ($SYNC_CMD) {
put "Syncing cache";
largeSlowStore($SET_CMD,index=>$_, value=>%index{$_}) for (@lru);
%index=();
@lru=();
}
when ($UPDATE_CMD) {
put "Updating cache: $index => $value";
my ($k)=(^@lru).grep({@lru[$_] == $index});
my $tmp;
$tmp=@lru.splice($k,1) when $k.defined;
my $del=@lru.shift unless @lru < $capacity;
if (defined $del) {
put "Cache overflow";
largeSlowStore($SET_CMD,index=>$del,value=>%index{$del});
%index{$del}:delete;
}
@lru.push: $index;
%index{$index}=$value;
}
when ($DUMP_CMD) {
put "LRU keys: ", @lru.join: ", ";
put "\n";
}
}
}
}
sub largeSlowStore($cmd,:$index,:$value) {
state @data= 10.rand.Int xx 10;
do {
given ($cmd) {
sleep(2.rand);
when ($GET_CMD) {
put "Read backing store";
@data[$index];
};
when ($SET_CMD) {
put "Write backing store";
@data[$index]=$value;
}
when ($DUMP_CMD) {
put @data.map({ defined($_)??$_!!"N/A"}).join: ", ";
put "";
}
}
}
}