Skip to content

Commit

Permalink
Extract ConcurrentLfuCore with generic node and policy (#520)
Browse files Browse the repository at this point in the history
  • Loading branch information
bitfaster authored Dec 3, 2023
1 parent fc969c8 commit e3cddc7
Show file tree
Hide file tree
Showing 6 changed files with 335 additions and 161 deletions.
29 changes: 15 additions & 14 deletions BitFaster.Caching.UnitTests/Lfu/ConcurrentLfuSoakTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -307,32 +307,33 @@ private async Task RunIntegrityCheckAsync(ConcurrentLfu<int, string> lfu, int it
RunIntegrityCheck(lfu, this.output);
}


private static void RunIntegrityCheck<K,V>(ConcurrentLfu<K,V> cache, ITestOutputHelper output)
{
new ConcurrentLfuIntegrityChecker<K, V>(cache).Validate(output);
new ConcurrentLfuIntegrityChecker<K, V, AccessOrderNode<K, V>, AccessOrderPolicy<K, V>>(cache.Core).Validate(output);
}
}

public class ConcurrentLfuIntegrityChecker<K, V>
internal class ConcurrentLfuIntegrityChecker<K, V, N, P>
where N : LfuNode<K, V>
where P : struct, INodePolicy<K, V, N>
{
private readonly ConcurrentLfu<K, V> cache;
private readonly ConcurrentLfuCore<K, V, N, P> cache;

private readonly LfuNodeList<K, V> windowLru;
private readonly LfuNodeList<K, V> probationLru;
private readonly LfuNodeList<K, V> protectedLru;

private readonly StripedMpscBuffer<LfuNode<K, V>> readBuffer;
private readonly MpscBoundedBuffer<LfuNode<K, V>> writeBuffer;
private readonly StripedMpscBuffer<N> readBuffer;
private readonly MpscBoundedBuffer<N> writeBuffer;

private static FieldInfo windowLruField = typeof(ConcurrentLfu<K, V>).GetField("windowLru", BindingFlags.NonPublic | BindingFlags.Instance);
private static FieldInfo probationLruField = typeof(ConcurrentLfu<K, V>).GetField("probationLru", BindingFlags.NonPublic | BindingFlags.Instance);
private static FieldInfo protectedLruField = typeof(ConcurrentLfu<K, V>).GetField("protectedLru", BindingFlags.NonPublic | BindingFlags.Instance);
private static FieldInfo windowLruField = typeof(ConcurrentLfuCore<K, V, N, P>).GetField("windowLru", BindingFlags.NonPublic | BindingFlags.Instance);
private static FieldInfo probationLruField = typeof(ConcurrentLfuCore<K, V, N, P>).GetField("probationLru", BindingFlags.NonPublic | BindingFlags.Instance);
private static FieldInfo protectedLruField = typeof(ConcurrentLfuCore<K, V, N, P>).GetField("protectedLru", BindingFlags.NonPublic | BindingFlags.Instance);

private static FieldInfo readBufferField = typeof(ConcurrentLfu<K, V>).GetField("readBuffer", BindingFlags.NonPublic | BindingFlags.Instance);
private static FieldInfo writeBufferField = typeof(ConcurrentLfu<K, V>).GetField("writeBuffer", BindingFlags.NonPublic | BindingFlags.Instance);
private static FieldInfo readBufferField = typeof(ConcurrentLfuCore<K, V, N, P>).GetField("readBuffer", BindingFlags.NonPublic | BindingFlags.Instance);
private static FieldInfo writeBufferField = typeof(ConcurrentLfuCore<K, V, N, P>).GetField("writeBuffer", BindingFlags.NonPublic | BindingFlags.Instance);

public ConcurrentLfuIntegrityChecker(ConcurrentLfu<K, V> cache)
public ConcurrentLfuIntegrityChecker(ConcurrentLfuCore<K, V, N, P> cache)
{
this.cache = cache;

Expand All @@ -341,8 +342,8 @@ public ConcurrentLfuIntegrityChecker(ConcurrentLfu<K, V> cache)
this.probationLru = (LfuNodeList<K, V>)probationLruField.GetValue(cache);
this.protectedLru = (LfuNodeList<K, V>)protectedLruField.GetValue(cache);

this.readBuffer = (StripedMpscBuffer<LfuNode<K, V>>)readBufferField.GetValue(cache);
this.writeBuffer = (MpscBoundedBuffer<LfuNode<K, V>>)writeBufferField.GetValue(cache);
this.readBuffer = (StripedMpscBuffer<N>)readBufferField.GetValue(cache);
this.writeBuffer = (MpscBoundedBuffer<N>)writeBufferField.GetValue(cache);
}

public void Validate(ITestOutputHelper output)
Expand Down
30 changes: 29 additions & 1 deletion BitFaster.Caching.UnitTests/Lfu/ConcurrentLfuTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,30 @@ public ConcurrentLfuTests(ITestOutputHelper output)
this.output = output;
}

[Fact]
public void WhenCapacityIsLessThan3CtorThrows()
{
Action constructor = () => { var x = new ConcurrentLfu<int, string>(2); };

constructor.Should().Throw<ArgumentOutOfRangeException>();
}

[Fact]
public void WhenCapacityIsValidCacheIsCreated()
{
var x = new ConcurrentLfu<int, string>(3);

x.Capacity.Should().Be(3);
}

[Fact]
public void WhenConcurrencyIsLessThan1CtorThrows()
{
Action constructor = () => { var x = new ConcurrentLfu<int, string>(0, 20, new ForegroundScheduler(), EqualityComparer<int>.Default); };

constructor.Should().Throw<ArgumentOutOfRangeException>();
}

[Fact]
public void DefaultSchedulerIsThreadPool()
{
Expand Down Expand Up @@ -548,7 +572,11 @@ public void WhenItemsAddedGenericEnumerateContainsKvps()
cache.GetOrAdd(1, k => k + 1);
cache.GetOrAdd(2, k => k + 1);

cache.Should().BeEquivalentTo(new[] { new KeyValuePair<int, int>(1, 2), new KeyValuePair<int, int>(2, 3) });
var enumerator = cache.GetEnumerator();
enumerator.MoveNext().Should().BeTrue();
enumerator.Current.Should().Be(new KeyValuePair<int, int>(1, 2));
enumerator.MoveNext().Should().BeTrue();
enumerator.Current.Should().Be(new KeyValuePair<int, int>(2, 3));
}

[Fact]
Expand Down
2 changes: 1 addition & 1 deletion BitFaster.Caching/BitFaster.Caching.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFrameworks>netstandard2.0;netcoreapp3.1;net6.0</TargetFrameworks>
<LangVersion>9.0</LangVersion>
<LangVersion>10.0</LangVersion>
<Authors>Alex Peck</Authors>
<Company />
<Product>BitFaster.Caching</Product>
Expand Down
Loading

0 comments on commit e3cddc7

Please sign in to comment.