Skip to content

Commit 775e9c0

Browse files
author
Alex Peck
committed
handle warm
1 parent 9ad8d8f commit 775e9c0

File tree

2 files changed

+85
-2
lines changed

2 files changed

+85
-2
lines changed

BitFaster.Caching.UnitTests/Lru/ConcurrentLruTests.cs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -684,10 +684,12 @@ public void WhenItemRemovedFromHotDuringWarmupItIsEagerlyCycledOut()
684684
lru.GetOrAdd(1, valueFactory.Create);
685685

686686
lru.TryRemove(1);
687+
Print(); // Hot [1] Warm [] Cold []
687688

688689
lru.GetOrAdd(1, valueFactory.Create);
689690
lru.GetOrAdd(2, valueFactory.Create);
690691
lru.GetOrAdd(3, valueFactory.Create);
692+
Print(); // Hot [1,2,3] Warm [] Cold []
691693

692694
lru.WarmCount.Should().Be(0);
693695
lru.ColdCount.Should().Be(0);
@@ -701,21 +703,67 @@ public void WhenItemRemovedFromHotAfterWarmupItIsEagerlyCycledOut()
701703
lru.GetOrAdd(i, valueFactory.Create);
702704
}
703705

706+
Print(); // Hot [6,7,8] Warm [1,2,3] Cold [0,4,5]
704707
lru.Metrics.Value.Evicted.Should().Be(0);
705-
708+
706709
lru.GetOrAdd(-1, valueFactory.Create);
707710

708711
lru.TryRemove(-1);
712+
Print(); // Hot[7, 8, -1] Warm[1, 2, 3] Cold[4, 5, 6]
709713

710714
// fully cycle hot, which is 3 items
711715
lru.GetOrAdd(-2, valueFactory.Create);
712716
lru.GetOrAdd(-3, valueFactory.Create);
713717
lru.GetOrAdd(-4, valueFactory.Create);
714718

719+
Print(); // Hot [-2,-3,-4] Warm [1,2,3] Cold [6,7,8]
720+
715721
// without eager eviction as -1 is purged from hot, a 4th item will pushed out since hot queue is full
716722
lru.Metrics.Value.Evicted.Should().Be(3);
717723
}
718724

725+
[Fact]
726+
public void WhenItemRemovedFromWarmDuringWarmupItIsEagerlyCycledOut()
727+
{
728+
lru.GetOrAdd(1, valueFactory.Create);
729+
lru.GetOrAdd(2, valueFactory.Create);
730+
lru.GetOrAdd(3, valueFactory.Create);
731+
lru.GetOrAdd(4, valueFactory.Create);
732+
Print(); // Hot [2,3,4] Warm [1] Cold []
733+
734+
lru.TryRemove(1);
735+
736+
lru.GetOrAdd(5, valueFactory.Create);
737+
lru.GetOrAdd(6, valueFactory.Create);
738+
lru.GetOrAdd(7, valueFactory.Create);
739+
Print(); // Hot [5,6,7] Warm [2,3,4] Cold []
740+
741+
lru.WarmCount.Should().Be(3);
742+
lru.ColdCount.Should().Be(0);
743+
}
744+
745+
746+
[Fact]
747+
public void WhenItemRemovedFromWarmAfterWarmupItIsEagerlyCycledOut()
748+
{
749+
for (int i = 0; i < lru.Capacity; i++)
750+
{
751+
lru.GetOrAdd(i, valueFactory.Create);
752+
}
753+
754+
Print(); // Hot [6,7,8] Warm [1,2,3] Cold [0,4,5]
755+
lru.Metrics.Value.Evicted.Should().Be(0);
756+
757+
lru.TryRemove(1);
758+
759+
lru.GetOrAdd(6, valueFactory.Create); // 6 -> W
760+
lru.GetOrAdd(9, valueFactory.Create);
761+
762+
Print(); // Hot [7,8,9] Warm [2,3,6] Cold [0,4,5]
763+
764+
lru.Metrics.Value.Evicted.Should().Be(0);
765+
}
766+
719767
[Fact]
720768
public void WhenKeyDoesNotExistTryRemoveReturnsFalse()
721769
{
@@ -1343,6 +1391,14 @@ private void Warmup()
13431391
lru.GetOrAdd(-8, valueFactory.Create);
13441392
lru.GetOrAdd(-9, valueFactory.Create);
13451393
}
1394+
1395+
1396+
private void Print()
1397+
{
1398+
#if DEBUG
1399+
this.testOutputHelper.WriteLine(this.lru.FormatLruString());
1400+
#endif
1401+
}
13461402
}
13471403

13481404
public class ConcurrentLruIntegrityChecker<K, V, I, P, T>

BitFaster.Caching/Lru/ConcurrentLruCore.cs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,11 @@ private void CycleDuringWarmup(int hotCount)
691691

692692
if (this.warmQueue.TryDequeue(out var item))
693693
{
694+
if (item.WasRemoved)
695+
{
696+
return (ItemDestination.Remove, 0);
697+
}
698+
694699
var where = this.itemPolicy.RouteWarm(item);
695700

696701
// When the warm queue is full, we allow an overflow of 1 item before redirecting warm items to cold.
@@ -754,7 +759,8 @@ private int LastWarmToCold()
754759

755760
if (this.warmQueue.TryDequeue(out var item))
756761
{
757-
return this.Move(item, ItemDestination.Cold, ItemRemovedReason.Evicted);
762+
var destination = item.WasRemoved ? ItemDestination.Remove : ItemDestination.Cold;
763+
return this.Move(item, destination, ItemRemovedReason.Evicted);
758764
}
759765
else
760766
{
@@ -818,6 +824,27 @@ IEnumerator IEnumerable.GetEnumerator()
818824
return ((ConcurrentLruCore<K, V, I, P, T>)this).GetEnumerator();
819825
}
820826

827+
#if DEBUG
828+
/// <summary>
829+
/// Format the LRU as a string by converting all the keys to strings.
830+
/// </summary>
831+
/// <returns>The LRU formatted as a string.</returns>
832+
public string FormatLruString()
833+
{
834+
var sb = new System.Text.StringBuilder();
835+
836+
sb.Append("Hot [");
837+
sb.Append(string.Join(",", this.hotQueue.Select(n => n.Key.ToString())));
838+
sb.Append("] Warm [");
839+
sb.Append(string.Join(",", this.warmQueue.Select(n => n.Key.ToString())));
840+
sb.Append("] Cold [");
841+
sb.Append(string.Join(",", this.coldQueue.Select(n => n.Key.ToString())));
842+
sb.Append(']');
843+
844+
return sb.ToString();
845+
}
846+
#endif
847+
821848
private static CachePolicy CreatePolicy(ConcurrentLruCore<K, V, I, P, T> lru)
822849
{
823850
var p = new Proxy(lru);

0 commit comments

Comments
 (0)