Skip to content

Commit

Permalink
cleanup merge
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Peck committed Dec 3, 2023
1 parent 1b7f5ce commit 73cdbae
Show file tree
Hide file tree
Showing 6 changed files with 21 additions and 49 deletions.
4 changes: 2 additions & 2 deletions BitFaster.Caching.UnitTests/Lfu/TimerWheelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ public class TimerWheelTests
[Fact]
public void Test()
{
var wheel = new TimerWheel<int, int>();
var wheel = new TimerWheel<int, int, TimeOrderNode<int, int>, ExpireAfterPolicy<int, int>>();
var policy = new ExpireAfterPolicy<int, int>(wheel);
var cache = new ConcurrentLfuCore<int, int, TimeOrderNode<int, int>, ExpireAfterPolicy<int, int>>(
Defaults.ConcurrencyLevel, 3, new ThreadPoolScheduler(), EqualityComparer<int>.Default, policy);
Defaults.ConcurrencyLevel, 3, new ThreadPoolScheduler(), EqualityComparer<int>.Default, () => { }, policy);

wheel.Should().NotBeNull();
}
Expand Down
38 changes: 2 additions & 36 deletions BitFaster.Caching/Lfu/ConcurrentLfu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,40 +10,6 @@

namespace BitFaster.Caching.Lfu
{
// TODO: making ConcurrentLfu with the Core base class required the following:
// - LfuNode public
// - INodePolicy public
// - AccessOrderPolicy public etc.
// This would be cleaner as a wrapper class, then all impl details can be internal and can be changed over time.
/// <summary>
/// Bounded size ConcurrentLfu
/// </summary>
public sealed class ConcurrentLfu<K, V> : ConcurrentLfuCore<K, V, AccessOrderNode<K, V>, AccessOrderPolicy<K, V>>
{
// TODO: this is now duped, but required for back compat against 2.4.0
public const int DefaultBufferSize = 128;

/// <summary>
/// Initializes a new instance of the ConcurrentLfu class with the specified capacity.
/// </summary>
/// <param name="capacity">The capacity.</param>
public ConcurrentLfu(int capacity)
: base(Defaults.ConcurrencyLevel, capacity, new ThreadPoolScheduler(), EqualityComparer<K>.Default, default)
{
}

/// <summary>
/// Initializes a new instance of the ConcurrentLfu class with the specified concurrencyLevel, capacity, scheduler, equality comparer and buffer size.
/// </summary>
/// <param name="concurrencyLevel">The concurrency level.</param>
/// <param name="capacity">The capacity.</param>
/// <param name="scheduler">The scheduler.</param>
/// <param name="comparer">The equality comparer.</param>
public ConcurrentLfu(int concurrencyLevel, int capacity, IScheduler scheduler, IEqualityComparer<K> comparer)
: base(concurrencyLevel, capacity, scheduler, comparer, default)
{ }
}

/// <summary>
/// An approximate LFU based on the W-TinyLfu eviction policy. W-TinyLfu tracks items using a window LRU list, and
/// a main space LRU divided into protected and probation segments. Reads and writes to the cache are stored in buffers
Expand Down Expand Up @@ -82,7 +48,7 @@ public sealed class ConcurrentLfu<K, V> : ICache<K, V>, IAsyncCache<K, V>, IBoun
/// <param name="capacity">The capacity.</param>
public ConcurrentLfu(int capacity)
{
this.core = new(Defaults.ConcurrencyLevel, capacity, new ThreadPoolScheduler(), EqualityComparer<K>.Default, () => this.DrainBuffers());
this.core = new(Defaults.ConcurrencyLevel, capacity, new ThreadPoolScheduler(), EqualityComparer<K>.Default, () => this.DrainBuffers(), default);
}

/// <summary>
Expand All @@ -94,7 +60,7 @@ public ConcurrentLfu(int capacity)
/// <param name="comparer">The equality comparer.</param>
public ConcurrentLfu(int concurrencyLevel, int capacity, IScheduler scheduler, IEqualityComparer<K> comparer)
{
this.core = new(concurrencyLevel, capacity, scheduler, comparer, () => this.DrainBuffers());
this.core = new(concurrencyLevel, capacity, scheduler, comparer, () => this.DrainBuffers(), default);
}

internal ConcurrentLfuCore<K, V, AccessOrderNode<K, V>, AccessOrderPolicy<K, V>> Core => core;
Expand Down
12 changes: 8 additions & 4 deletions BitFaster.Caching/Lfu/ConcurrentLfuCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ internal struct ConcurrentLfuCore<K, V, N, P> : IBoundedPolicy

private readonly N[] drainBuffer;

public ConcurrentLfuCore(int concurrencyLevel, int capacity, IScheduler scheduler, IEqualityComparer<K> comparer, Action drainBuffers)
private P policy;

public ConcurrentLfuCore(int concurrencyLevel, int capacity, IScheduler scheduler, IEqualityComparer<K> comparer, Action drainBuffers, P policy)
{
if (capacity < 3)
Throw.ArgOutOfRange(nameof(capacity));
Expand Down Expand Up @@ -98,6 +100,8 @@ public ConcurrentLfuCore(int concurrencyLevel, int capacity, IScheduler schedule
this.drainBuffer = new N[this.readBuffer.Capacity];

this.drainBuffers = drainBuffers;

this.policy = policy;
}

// No lock count: https://arbel.net/2013/02/03/best-practices-for-using-concurrentdictionary/
Expand All @@ -124,7 +128,7 @@ public void AddOrUpdate(K key, V value)
return;
}

var node = default(P).Create(key, value);
var node = policy.Create(key, value);
if (this.dictionary.TryAdd(key, node))
{
AfterWrite(node);
Expand Down Expand Up @@ -174,7 +178,7 @@ public void Trim(int itemCount)

private bool TryAdd(K key, V value)
{
var node = default(P).Create(key, value);
var node = policy.Create(key, value);

if (this.dictionary.TryAdd(key, node))
{
Expand Down Expand Up @@ -749,7 +753,7 @@ private bool AdmitCandidate(K candidateKey, K victimKey)
return candidateFreq > victimFreq;
}

private void Evict(LfuNode<K, V> evictee)
internal void Evict(LfuNode<K, V> evictee)
{
this.dictionary.TryRemove(evictee.Key, out var _);
evictee.list.Remove(evictee);
Expand Down
2 changes: 1 addition & 1 deletion BitFaster.Caching/Lfu/LfuNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public AccessOrderExpiringNode(K k, V v) : base(k, v)
// both ExpireAfter and ExpireAfterWrite require
// 1. Duration
// 2. Doubly linked list
public sealed class TimeOrderNode<K, V> : LfuNode<K, V>
internal sealed class TimeOrderNode<K, V> : LfuNode<K, V>
{
TimeOrderNode<K, V> prevV;
TimeOrderNode<K, V> nextV;
Expand Down
4 changes: 2 additions & 2 deletions BitFaster.Caching/Lfu/NodePolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ public AccessOrderNode<K, V> Create(K key, V value)

internal struct ExpireAfterPolicy<K, V> : INodePolicy<K, V, TimeOrderNode<K, V>>
{
private readonly TimerWheel<K, V> wheel;
private readonly TimerWheel<K, V, TimeOrderNode<K, V>, ExpireAfterPolicy<K, V>> wheel;

// TODO: expiry calculator

Check notice

Code scanning / devskim

A "TODO" or similar was left in source code, possibly indicating incomplete functionality Note

Suspicious comment

public ExpireAfterPolicy(TimerWheel<K, V> wheel)
public ExpireAfterPolicy(TimerWheel<K, V, TimeOrderNode<K, V>, ExpireAfterPolicy<K, V>> wheel)
{
this.wheel = wheel;
}
Expand Down
10 changes: 6 additions & 4 deletions BitFaster.Caching/Lfu/TimerWheel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ namespace BitFaster.Caching.Lfu
{
// Port TimerWheel from Caffeine
// https://github.com/ben-manes/caffeine/blob/73d5011f9db373fc20a6e12d1f194f0d7a967d69/caffeine/src/main/java/com/github/benmanes/caffeine/cache/TimerWheel.java#L36
public class TimerWheel<K, V>
internal class TimerWheel<K, V, N, P>
where N : LfuNode<K, V>
where P : struct, INodePolicy<K, V, N>
{
static readonly int[] BUCKETS = { 64, 64, 32, 4, 1 };

Expand Down Expand Up @@ -48,7 +50,7 @@ public TimerWheel()
/// </summary>
/// <param name="cache"></param>
/// <param name="currentTimeNanos"></param>
public void Advance(ConcurrentLfu<K, V> cache, long currentTimeNanos)
public void Advance(ref ConcurrentLfuCore<K, V, N, P> cache, long currentTimeNanos)
{
long previousTimeNanos = nanos;
nanos = currentTimeNanos;
Expand All @@ -74,7 +76,7 @@ public void Advance(ConcurrentLfu<K, V> cache, long currentTimeNanos)
{
break;
}
Expire(cache, i, previousTicks, delta);
Expire(ref cache, i, previousTicks, delta);
}
}
catch (Exception t)

Check warning on line 82 in BitFaster.Caching/Lfu/TimerWheel.cs

View workflow job for this annotation

GitHub Actions / infer

The variable 't' is declared but never used

Check warning on line 82 in BitFaster.Caching/Lfu/TimerWheel.cs

View workflow job for this annotation

GitHub Actions / infer

The variable 't' is declared but never used

Check warning on line 82 in BitFaster.Caching/Lfu/TimerWheel.cs

View workflow job for this annotation

GitHub Actions / linux

The variable 't' is declared but never used

Check warning on line 82 in BitFaster.Caching/Lfu/TimerWheel.cs

View workflow job for this annotation

GitHub Actions / linux

The variable 't' is declared but never used

Check warning on line 82 in BitFaster.Caching/Lfu/TimerWheel.cs

View workflow job for this annotation

GitHub Actions / bench-win

The variable 't' is declared but never used

Check warning on line 82 in BitFaster.Caching/Lfu/TimerWheel.cs

View workflow job for this annotation

GitHub Actions / bench-win

The variable 't' is declared but never used

Check warning on line 82 in BitFaster.Caching/Lfu/TimerWheel.cs

View workflow job for this annotation

GitHub Actions / bench-macos

The variable 't' is declared but never used

Check warning on line 82 in BitFaster.Caching/Lfu/TimerWheel.cs

View workflow job for this annotation

GitHub Actions / bench-macos

The variable 't' is declared but never used

Check warning on line 82 in BitFaster.Caching/Lfu/TimerWheel.cs

View workflow job for this annotation

GitHub Actions / bench-linux

The variable 't' is declared but never used

Check warning on line 82 in BitFaster.Caching/Lfu/TimerWheel.cs

View workflow job for this annotation

GitHub Actions / bench-linux

The variable 't' is declared but never used

Check warning on line 82 in BitFaster.Caching/Lfu/TimerWheel.cs

View workflow job for this annotation

GitHub Actions / mac

The variable 't' is declared but never used

Check warning on line 82 in BitFaster.Caching/Lfu/TimerWheel.cs

View workflow job for this annotation

GitHub Actions / mac

The variable 't' is declared but never used

Check warning on line 82 in BitFaster.Caching/Lfu/TimerWheel.cs

View workflow job for this annotation

GitHub Actions / win

The variable 't' is declared but never used

Check warning on line 82 in BitFaster.Caching/Lfu/TimerWheel.cs

View workflow job for this annotation

GitHub Actions / win

The variable 't' is declared but never used

Check warning on line 82 in BitFaster.Caching/Lfu/TimerWheel.cs

View workflow job for this annotation

GitHub Actions / win

The variable 't' is declared but never used
Expand All @@ -85,7 +87,7 @@ public void Advance(ConcurrentLfu<K, V> cache, long currentTimeNanos)
}

// Expires entries or reschedules into the proper bucket if still active.
private void Expire(ConcurrentLfu<K, V> cache, int index, long previousTicks, long delta)
private void Expire(ref ConcurrentLfuCore<K, V, N, P> cache, int index, long previousTicks, long delta)
{
TimeOrderNode<K, V>[] timerWheel = wheel[index];
int mask = timerWheel.Length - 1;
Expand Down

0 comments on commit 73cdbae

Please sign in to comment.