Skip to content

Commit 974d7a1

Browse files
authored
TinyLfu policy (#190)
* correct * next => prev * tests * rem unreachable * cleanup
1 parent b997777 commit 974d7a1

File tree

4 files changed

+249
-49
lines changed

4 files changed

+249
-49
lines changed

BitFaster.Caching.UnitTests/Lfu/ConcurrentLfuTests.cs

Lines changed: 121 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,68 @@ public void WhenItemsAddedExceedsCapacityItemsAreDiscarded()
5555
cache.Count.Should().Be(20);
5656
}
5757

58+
// protected 15
59+
// probation 4
60+
// window 1
61+
[Fact]
62+
public void WhenNewItemsAreAddedTheyArePromotedBasedOnFrequency()
63+
{
64+
for (int i = 0; i < 20; i++)
65+
{
66+
cache.GetOrAdd(i, k => k);
67+
}
68+
69+
// W [19] Protected [] Probation [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18]
70+
cache.PendingMaintenance();
71+
LogLru();
72+
73+
for (int i = 0; i < 15; i++)
74+
{
75+
cache.GetOrAdd(i, k => k);
76+
}
77+
78+
// W [19] Protected [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14] Probation [15,16,17,18]
79+
cache.PendingMaintenance();
80+
LogLru();
81+
82+
for (int k = 0; k < 2; k++)
83+
{
84+
for (int j = 0; j < 6; j++)
85+
{
86+
for (int i = 0; i < 15; i++)
87+
{
88+
cache.GetOrAdd(j + 20, k => k);
89+
}
90+
cache.PendingMaintenance();
91+
LogLru();
92+
}
93+
}
94+
95+
// Values promoted to probation then protected:
96+
// W[21] Protected[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] Probation[16, 17, 18, 20]
97+
// W[22] Protected[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] Probation[17, 18, 20, 21]
98+
// W[23] Protected[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] Probation[18, 20, 21, 22]
99+
// W[24] Protected[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] Probation[20, 21, 22, 23]
100+
// W[25] Protected[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] Probation[20, 21, 22, 23]
101+
// W[25] Protected[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 20] Probation[21, 22, 23, 0]
102+
// W[25] Protected[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 20, 21] Probation[22, 23, 0, 1]
103+
// W[25] Protected[3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 20, 21, 22] Probation[23, 0, 1, 2]
104+
// W[25] Protected[4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 20, 21, 22, 23] Probation[0, 1, 2, 3]
105+
// W[24] Protected[4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 20, 21, 22, 23] Probation[1, 2, 3, 25]
106+
// W[24] Protected[5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 20, 21, 22, 23, 25] Probation[1, 2, 3, 4]
107+
108+
cache.Count.Should().Be(20);
109+
110+
// W [24] Protected [5,6,7,8,9,10,11,12,13,14,20,21,22,23,25] Probation []
111+
cache.Trim(4);
112+
cache.PendingMaintenance();
113+
LogLru();
114+
115+
cache.TryGet(1, out var value1).Should().BeFalse();
116+
cache.TryGet(2, out var value2).Should().BeFalse();
117+
cache.Count.Should().Be(16);
118+
}
119+
58120
[Fact]
59121
public void ReadPromotesProbation()
60122
{
@@ -68,7 +130,7 @@ public void ReadPromotesProbation()
68130
cache.GetOrAdd(i, k => k);
69131
}
70132

71-
// W [24] Protected [1,2,0,3,4,5,6,7,8,9,10,11,12,13,14] Probation [15,16,17,18]
133+
// W [24] Protected [] Probation [1,2,0,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18]
72134
cache.PendingMaintenance();
73135
LogLru();
74136

@@ -80,13 +142,13 @@ public void ReadPromotesProbation()
80142
cache.GetOrAdd(i, k => k);
81143
}
82144

83-
// W [49] Protected [2,0,3,4,5,6,7,8,9,10,11,12,13,14,16] Probation [1,25,26,27]
145+
// W [49] Protected [16] Probation [1,2,0,3,4,5,6,7,8,9,10,11,12,13,14,15,17,18]
84146
cache.PendingMaintenance();
85147
LogLru();
86148

87-
cache.Trim(5);
149+
cache.Trim(18);
88150

89-
// W [49] Protected [0,3,4,5,6,7,8,9,10,11,12,13,14,16] Probation []
151+
// W [49] Protected [16] Probation []
90152
cache.PendingMaintenance();
91153
LogLru();
92154

@@ -107,7 +169,7 @@ public void WritePromotesProbation()
107169
cache.GetOrAdd(i, k => k);
108170
}
109171

110-
// W [24] Protected [1,2,0,3,4,5,6,7,8,9,10,11,12,13,14] Probation [15,16,17,18]
172+
// W [24] Protected [] Probation [1,2,0,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18]
111173
cache.PendingMaintenance();
112174
LogLru();
113175

@@ -119,39 +181,85 @@ public void WritePromotesProbation()
119181
cache.GetOrAdd(i, k => k);
120182
}
121183

122-
// W [49] Protected [2,0,3,4,5,6,7,8,9,10,11,12,13,14,16] Probation [1,25,26,27]
184+
// [49] Protected [16] Probation [1,2,0,3,4,5,6,7,8,9,10,11,12,13,14,15,17,18]
123185
cache.PendingMaintenance();
124186
LogLru();
125187

126-
cache.Trim(5);
188+
cache.Trim(18);
127189

128-
// W [49] Protected [0,3,4,5,6,7,8,9,10,11,12,13,14,16] Probation []
190+
// W [49] Protected [16] Probation []
129191
cache.PendingMaintenance();
130192
LogLru();
131193

132194
cache.TryGet(16, out var value1).Should().BeTrue();
133195
}
134196

135197
[Fact]
136-
public void WriteUpdateProtectedLruOrder()
198+
public void ReadUpdatesProtectedLruOrder()
137199
{
138-
// W [19], Protected [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], Probation [15, 16, 17, 18]
200+
// W [19] Protected [] Probation [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18]
139201
for (int i = 0; i < 20; i++)
140202
{
141203
cache.GetOrAdd(i, k => k);
142204
}
143205

144206
cache.PendingMaintenance();
207+
LogLru();
208+
209+
cache.GetOrAdd(7, k => k);
210+
cache.GetOrAdd(8, k => k);
211+
cache.GetOrAdd(9, k => k);
145212

146-
// W [19], Protected [0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 7], Probation [15, 16, 17, 18]
213+
// W [19] Protected [7,8,9] Probation [0,1,2,3,4,5,6,10,11,12,13,14,15,16,17,18]
214+
cache.PendingMaintenance();
215+
LogLru();
216+
217+
// W [19] Protected [8,9,7] Probation [0,1,2,3,4,5,6,10,11,12,13,14,15,16,17,18]
218+
// element 7 now moved to back of LRU
219+
cache.GetOrAdd(7, k => k);
220+
cache.PendingMaintenance();
221+
LogLru();
222+
223+
// Trim is LRU order
224+
//W [19] Protected [7] Probation []
225+
cache.Trim(18);
226+
cache.PendingMaintenance();
227+
LogLru();
228+
229+
cache.TryGet(7, out var _).Should().BeTrue();
230+
}
231+
232+
[Fact]
233+
public void WriteUpdatesProtectedLruOrder()
234+
{
235+
// W [19] Protected [] Probation [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18]
236+
for (int i = 0; i < 20; i++)
237+
{
238+
cache.GetOrAdd(i, k => k);
239+
}
240+
241+
cache.PendingMaintenance();
242+
LogLru();
243+
244+
cache.GetOrAdd(7, k => k);
245+
cache.GetOrAdd(8, k => k);
246+
cache.GetOrAdd(9, k => k);
247+
248+
// W [19] Protected [7,8,9] Probation [0,1,2,3,4,5,6,10,11,12,13,14,15,16,17,18]
249+
cache.PendingMaintenance();
250+
LogLru();
251+
252+
// W [19] Protected [8,9,7] Probation [0,1,2,3,4,5,6,10,11,12,13,14,15,16,17,18]
147253
// element 7 now moved to back of LRU
148254
cache.TryUpdate(7, -7).Should().BeTrue();
149255
cache.PendingMaintenance();
256+
LogLru();
150257

151258
// Trim is LRU order
152-
// W [19], Protected [9, 10, 11, 12, 14, 7], Probation []
153-
cache.Trim(12);
259+
//W [19] Protected [7] Probation []
260+
cache.Trim(18);
154261
cache.PendingMaintenance();
262+
LogLru();
155263

156264
cache.TryGet(7, out var _).Should().BeTrue();
157265
}

0 commit comments

Comments
 (0)