Skip to content

Commit 4d52e6f

Browse files
authored
Lfu soak test cleanup (#441)
* params * dedupe ---------
1 parent c7b399e commit 4d52e6f

File tree

1 file changed

+67
-91
lines changed

1 file changed

+67
-91
lines changed

BitFaster.Caching.UnitTests/Lfu/ConcurrentLfuSoakTests.cs

Lines changed: 67 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -14,203 +14,179 @@ namespace BitFaster.Caching.UnitTests.Lfu
1414
[Collection("Soak")]
1515
public class ConcurrentLfuSoakTests
1616
{
17-
private const int iterations = 10;
17+
private const int soakIterations = 10;
18+
private const int threads = 4;
19+
private const int loopIterations = 100_000;
20+
1821
private readonly ITestOutputHelper output;
1922
public ConcurrentLfuSoakTests(ITestOutputHelper testOutputHelper)
2023
{
2124
this.output = testOutputHelper;
2225
}
2326

2427
[Theory]
25-
[Repeat(iterations)]
28+
[Repeat(soakIterations)]
2629
public async Task WhenConcurrentGetCacheEndsInConsistentState(int iteration)
2730
{
28-
var scheduler = new BackgroundThreadScheduler();
29-
var lfu = new ConcurrentLfuBuilder<int, string>().WithCapacity(9).WithScheduler(scheduler).Build() as ConcurrentLfu<int, string>;
31+
var lfu = CreateWithBackgroundScheduler();
3032

31-
await Threaded.Run(4, () => {
32-
for (int i = 0; i < 100000; i++)
33+
await Threaded.Run(threads, () => {
34+
for (int i = 0; i < loopIterations; i++)
3335
{
3436
lfu.GetOrAdd(i + 1, i => i.ToString());
3537
}
3638
});
37-
38-
this.output.WriteLine($"iteration {iteration} keys={string.Join(" ", lfu.Keys)}");
39-
40-
scheduler.Dispose();
41-
await scheduler.Completion;
42-
43-
RunIntegrityCheck(lfu);
39+
40+
await RunIntegrityCheckAsync(lfu, iteration);
4441
}
4542

4643
[Theory]
47-
[Repeat(iterations)]
44+
[Repeat(soakIterations)]
4845
public async Task WhenConcurrentGetAsyncCacheEndsInConsistentState(int iteration)
4946
{
50-
var scheduler = new BackgroundThreadScheduler();
51-
var lfu = new ConcurrentLfuBuilder<int, string>().WithCapacity(9).WithScheduler(scheduler).Build() as ConcurrentLfu<int, string>;
47+
var lfu = CreateWithBackgroundScheduler();
5248

53-
await Threaded.RunAsync(4, async () => {
54-
for (int i = 0; i < 100000; i++)
49+
await Threaded.RunAsync(threads, async () => {
50+
for (int i = 0; i < loopIterations; i++)
5551
{
5652
await lfu.GetOrAddAsync(i + 1, i => Task.FromResult(i.ToString()));
5753
}
58-
});
59-
60-
this.output.WriteLine($"iteration {iteration} keys={string.Join(" ", lfu.Keys)}");
61-
62-
scheduler.Dispose();
63-
await scheduler.Completion;
54+
});
6455

65-
RunIntegrityCheck(lfu);
56+
await RunIntegrityCheckAsync(lfu, iteration);
6657
}
6758

6859
[Theory]
69-
[Repeat(iterations)]
60+
[Repeat(soakIterations)]
7061
public async Task WhenConcurrentGetWithArgCacheEndsInConsistentState(int iteration)
7162
{
72-
var scheduler = new BackgroundThreadScheduler();
73-
var lfu = new ConcurrentLfuBuilder<int, string>().WithCapacity(9).WithScheduler(scheduler).Build() as ConcurrentLfu<int, string>;
63+
var lfu = CreateWithBackgroundScheduler();
7464

75-
await Threaded.Run(4, () => {
76-
for (int i = 0; i < 100000; i++)
65+
await Threaded.Run(threads, () => {
66+
for (int i = 0; i < loopIterations; i++)
7767
{
7868
// use the arg overload
7969
lfu.GetOrAdd(i + 1, (i, s) => i.ToString(), "Foo");
8070
}
8171
});
8272

83-
this.output.WriteLine($"iteration {iteration} keys={string.Join(" ", lfu.Keys)}");
84-
85-
scheduler.Dispose();
86-
await scheduler.Completion;
87-
88-
RunIntegrityCheck(lfu);
73+
await RunIntegrityCheckAsync(lfu, iteration);
8974
}
9075

9176
[Theory]
92-
[Repeat(iterations)]
77+
[Repeat(soakIterations)]
9378
public async Task WhenConcurrentGetAsyncWithArgCacheEndsInConsistentState(int iteration)
9479
{
95-
var scheduler = new BackgroundThreadScheduler();
96-
var lfu = new ConcurrentLfuBuilder<int, string>().WithCapacity(9).WithScheduler(scheduler).Build() as ConcurrentLfu<int, string>;
80+
var lfu = CreateWithBackgroundScheduler();
9781

98-
await Threaded.RunAsync(4, async () => {
99-
for (int i = 0; i < 100000; i++)
82+
await Threaded.RunAsync(threads, async () => {
83+
for (int i = 0; i < loopIterations; i++)
10084
{
10185
// use the arg overload
10286
await lfu.GetOrAddAsync(i + 1, (i, s) => Task.FromResult(i.ToString()), "Foo");
10387
}
10488
});
10589

106-
this.output.WriteLine($"iteration {iteration} keys={string.Join(" ", lfu.Keys)}");
107-
108-
scheduler.Dispose();
109-
await scheduler.Completion;
110-
111-
RunIntegrityCheck(lfu);
90+
await RunIntegrityCheckAsync(lfu, iteration);
11291
}
11392

11493
[Theory]
115-
[Repeat(iterations)]
94+
[Repeat(soakIterations)]
11695
public async Task WhenConcurrentGetAndUpdateCacheEndsInConsistentState(int iteration)
11796
{
118-
var scheduler = new BackgroundThreadScheduler();
119-
var lfu = new ConcurrentLfuBuilder<int, string>().WithCapacity(9).WithScheduler(scheduler).Build() as ConcurrentLfu<int, string>;
97+
var lfu = CreateWithBackgroundScheduler();
12098

121-
await Threaded.Run(4, () => {
122-
for (int i = 0; i < 100000; i++)
99+
await Threaded.Run(threads, () => {
100+
for (int i = 0; i < loopIterations; i++)
123101
{
124102
lfu.TryUpdate(i + 1, i.ToString());
125103
lfu.GetOrAdd(i + 1, i => i.ToString());
126104
}
127105
});
128106

129-
this.output.WriteLine($"iteration {iteration} keys={string.Join(" ", lfu.Keys)}");
130-
131-
scheduler.Dispose();
132-
await scheduler.Completion;
133-
134-
RunIntegrityCheck(lfu);
107+
await RunIntegrityCheckAsync(lfu, iteration);
135108
}
136109

137110
[Theory]
138-
[Repeat(iterations)]
111+
[Repeat(soakIterations)]
139112
public async Task WhenSoakConcurrentGetAndRemoveCacheEndsInConsistentState(int iteration)
140113
{
141-
var scheduler = new BackgroundThreadScheduler();
142-
var lfu = new ConcurrentLfuBuilder<int, string>().WithCapacity(9).WithScheduler(scheduler).Build() as ConcurrentLfu<int, string>;
114+
var lfu = CreateWithBackgroundScheduler();
143115

144-
await Threaded.Run(4, () => {
145-
for (int i = 0; i < 100000; i++)
116+
await Threaded.Run(threads, () => {
117+
for (int i = 0; i < loopIterations; i++)
146118
{
147119
lfu.TryRemove(i + 1);
148120
lfu.GetOrAdd(i + 1, i => i.ToString());
149121
}
150122
});
151123

152-
this.output.WriteLine($"iteration {iteration} keys={string.Join(" ", lfu.Keys)}");
153-
154-
scheduler.Dispose();
155-
await scheduler.Completion;
156-
157-
RunIntegrityCheck(lfu);
124+
await RunIntegrityCheckAsync(lfu, iteration);
158125
}
159126

160127
[Theory]
161-
[Repeat(iterations)]
128+
[Repeat(soakIterations)]
162129
public async Task WhenConcurrentGetAndRemoveKvpCacheEndsInConsistentState(int iteration)
163130
{
164-
var scheduler = new BackgroundThreadScheduler();
165-
var lfu = new ConcurrentLfuBuilder<int, string>().WithCapacity(9).WithScheduler(scheduler).Build() as ConcurrentLfu<int, string>;
131+
var lfu = CreateWithBackgroundScheduler();
166132

167-
await Threaded.Run(4, () => {
168-
for (int i = 0; i < 100000; i++)
133+
await Threaded.Run(threads, () => {
134+
for (int i = 0; i < loopIterations; i++)
169135
{
170136
lfu.TryRemove(new KeyValuePair<int, string>(i + 1, (i + 1).ToString()));
171137
lfu.GetOrAdd(i + 1, i => i.ToString());
172138
}
173139
});
174140

175-
this.output.WriteLine($"iteration {iteration} keys={string.Join(" ", lfu.Keys)}");
176-
177-
scheduler.Dispose();
178-
await scheduler.Completion;
179-
180-
RunIntegrityCheck(lfu);
141+
await RunIntegrityCheckAsync(lfu, iteration);
181142
}
182143

183144
[Fact]
184145
public async Task ThreadedVerifyMisses()
185146
{
186147
// buffer size is 1, this will cause dropped writes on some threads where the buffer is full
187-
var cache = new ConcurrentLfu<int, int>(1, 20, new NullScheduler(), EqualityComparer<int>.Default);
188-
189-
int threads = 4;
190-
int iterations = 100_000;
148+
var cache = new ConcurrentLfu<int, string>(1, 20, new NullScheduler(), EqualityComparer<int>.Default);
191149

192150
await Threaded.Run(threads, i =>
193151
{
194-
Func<int, int> func = x => x;
152+
Func<int, string> func = x => x.ToString();
195153

196-
int start = i * iterations;
154+
int start = i * loopIterations;
197155

198-
for (int j = start; j < start + iterations; j++)
156+
for (int j = start; j < start + loopIterations; j++)
199157
{
200158
cache.GetOrAdd(j, func);
201159
}
202160
});
203161

204-
var samplePercent = cache.Metrics.Value.Misses / (double)iterations / threads * 100;
162+
var samplePercent = cache.Metrics.Value.Misses / (double)loopIterations / threads * 100;
205163

206164
this.output.WriteLine($"Cache misses {cache.Metrics.Value.Misses} (sampled {samplePercent}%)");
207165
this.output.WriteLine($"Maintenance ops {cache.Scheduler.RunCount}");
208166

209-
cache.Metrics.Value.Misses.Should().Be(iterations * threads);
167+
cache.Metrics.Value.Misses.Should().Be(loopIterations * threads);
210168
RunIntegrityCheck(cache);
211-
}
169+
}
170+
171+
private ConcurrentLfu<int, string> CreateWithBackgroundScheduler()
172+
{
173+
var scheduler = new BackgroundThreadScheduler();
174+
return new ConcurrentLfuBuilder<int, string>().WithCapacity(9).WithScheduler(scheduler).Build() as ConcurrentLfu<int, string>;
175+
}
176+
177+
private async Task RunIntegrityCheckAsync(ConcurrentLfu<int, string> lfu, int iteration)
178+
{
179+
this.output.WriteLine($"iteration {iteration} keys={string.Join(" ", lfu.Keys)}");
180+
181+
var scheduler = lfu.Scheduler as BackgroundThreadScheduler;
182+
scheduler.Dispose();
183+
await scheduler.Completion;
184+
185+
RunIntegrityCheck(lfu);
186+
}
187+
212188

213-
private void RunIntegrityCheck<K,V>(ConcurrentLfu<K,V> cache)
189+
private static void RunIntegrityCheck<K,V>(ConcurrentLfu<K,V> cache)
214190
{
215191
new ConcurrentLfuIntegrityChecker<K, V>(cache).Validate();
216192
}

0 commit comments

Comments
 (0)