Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions BitFaster.Caching.UnitTests/Lru/ClassicLruTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,23 @@ public void WhenMoreKeysRequestedThanCapacityOldestItemIsEvicted()
valueFactory.timesCalled.Should().Be(capacity + 2);
}

[Fact]
public void WhenMoreKeysRequestedThanCapacityEvictedMetricRecordsNumberEvicted()
{
// request 3 items, LRU is now full
for (int i = 0; i < capacity; i++)
{
lru.GetOrAdd(i, valueFactory.Create);
}

lru.Metrics.Evicted.Should().Be(0);

// request 0, now item 1 is to be evicted
lru.GetOrAdd(4, valueFactory.Create);

lru.Metrics.Evicted.Should().Be(1);
}

[Fact]
public void WhenValueExpiresItIsDisposed()
{
Expand Down
10 changes: 10 additions & 0 deletions BitFaster.Caching.UnitTests/Lru/ConcurrentLruTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,16 @@ public void WhenValueEvictedItemRemovedEventIsFired()
removedItems[1].Reason.Should().Be(ItemRemovedReason.Evicted);
}

[Fact]
public void WhenValuesAreEvictedEvictionMetricCountsEvicted()
{
this.Warmup();

this.lru.GetOrAdd(1, valueFactory.Create);

this.lru.Metrics.Evicted.Should().Be(1);
}

[Fact]
public void WhenItemRemovedEventIsUnregisteredEventIsNotFired()
{
Expand Down
6 changes: 6 additions & 0 deletions BitFaster.Caching.UnitTests/Lru/NoTelemetryPolicyTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ public void MissesIsZero()
counter.Misses.Should().Be(0);
}

[Fact]
public void EvictedIsZero()
{
counter.Evicted.Should().Be(0);
}

[Fact]
public void IsEnabledIsFalse()
{
Expand Down
16 changes: 16 additions & 0 deletions BitFaster.Caching.UnitTests/Lru/TelemetryPolicyTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,22 @@ public void WhenTotalCountIsZeroRatioReturnsZero()
telemetryPolicy.HitRatio.Should().Be(0.0);
}

[Fact]
public void WhenItemRemovedIsEvictedIncrementEvictedCount()
{
telemetryPolicy.OnItemRemoved(1, 2, ItemRemovedReason.Evicted);

telemetryPolicy.Evicted.Should().Be(1);
}

[Fact]
public void WhenItemRemovedIsRemovedDontIncrementEvictedCount()
{
telemetryPolicy.OnItemRemoved(1, 2, ItemRemovedReason.Removed);

telemetryPolicy.Evicted.Should().Be(0);
}

[Fact]
public void WhenOnItemRemovedInvokedEventIsFired()
{
Expand Down
5 changes: 5 additions & 0 deletions BitFaster.Caching/ICacheMetrics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ public interface ICacheMetrics
/// </summary>
long Misses { get; }

/// <summary>
/// Gets the total number of evicted items.
/// </summary>
long Evicted { get; }

/// <summary>
/// Gets a value indicating whether metrics are enabled.
/// </summary>
Expand Down
6 changes: 6 additions & 0 deletions BitFaster.Caching/Lru/ClassicLru.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ public V GetOrAdd(K key, Func<K, V> valueFactory)
{
dictionary.TryRemove(first.Value.Key, out var removed);

Interlocked.Increment(ref this.metrics.evictedCount);
Disposer<V>.Dispose(removed.Value.Value);
}

Expand Down Expand Up @@ -179,6 +180,7 @@ public async Task<V> GetOrAddAsync(K key, Func<K, Task<V>> valueFactory)
{
dictionary.TryRemove(first.Value.Key, out var removed);

Interlocked.Increment(ref this.metrics.evictedCount);
Disposer<V>.Dispose(removed.Value.Value);
}

Expand Down Expand Up @@ -267,6 +269,7 @@ public void AddOrUpdate(K key, V value)
{
dictionary.TryRemove(first.Value.Key, out var removed);

Interlocked.Increment(ref this.metrics.evictedCount);
Disposer<V>.Dispose(removed.Value.Value);
}

Expand Down Expand Up @@ -374,6 +377,7 @@ private class CacheMetrics : ICacheMetrics
{
public long requestHitCount;
public long requestTotalCount;
public long evictedCount;

public double HitRatio => (double)requestHitCount / (double)requestTotalCount;

Expand All @@ -383,6 +387,8 @@ private class CacheMetrics : ICacheMetrics

public long Misses => requestTotalCount - requestHitCount;

public long Evicted => evictedCount;

public bool IsEnabled => true;
}
}
Expand Down
2 changes: 2 additions & 0 deletions BitFaster.Caching/Lru/NoTelemetryPolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public struct NoTelemetryPolicy<K, V> : ITelemetryPolicy<K, V>

public long Misses => 0;

public long Evicted => 0;

public bool IsEnabled => false;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down
8 changes: 8 additions & 0 deletions BitFaster.Caching/Lru/TelemetryPolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public struct TelemetryPolicy<K, V> : ITelemetryPolicy<K, V>
{
private long hitCount;
private long missCount;
private long evictedCount;
private object eventSource;

public double HitRatio => Total == 0 ? 0 : (double)hitCount / (double)Total;
Expand All @@ -22,6 +23,8 @@ public struct TelemetryPolicy<K, V> : ITelemetryPolicy<K, V>

public long Misses => this.missCount;

public long Evicted => this.evictedCount;

public bool IsEnabled => true;

public EventHandler<ItemRemovedEventArgs<K, V>> ItemRemoved;
Expand All @@ -38,6 +41,11 @@ public void IncrementHit()

public void OnItemRemoved(K key, V value, ItemRemovedReason reason)
{
if (reason == ItemRemovedReason.Evicted)
{
Interlocked.Increment(ref this.evictedCount);
}

// passing 'this' as source boxes the struct, and is anyway the wrong object
this.ItemRemoved?.Invoke(this.eventSource, new ItemRemovedEventArgs<K, V>(key, value, reason));
}
Expand Down