diff --git a/BitFaster.Caching.UnitTests/Lru/ConcurrentLruTests.cs b/BitFaster.Caching.UnitTests/Lru/ConcurrentLruTests.cs index 4c5d5266..b891225f 100644 --- a/BitFaster.Caching.UnitTests/Lru/ConcurrentLruTests.cs +++ b/BitFaster.Caching.UnitTests/Lru/ConcurrentLruTests.cs @@ -562,11 +562,10 @@ public void WhenValueExpiresItIsDisposed() lruOfDisposable.GetOrAdd(i, disposableValueFactory.Create); } - disposableValueFactory.Items[0].IsDisposed.Should().BeFalse(); - disposableValueFactory.Items[1].IsDisposed.Should().BeFalse(); - - disposableValueFactory.Items[2].IsDisposed.Should().BeTrue(); + disposableValueFactory.Items[0].IsDisposed.Should().BeTrue(); + disposableValueFactory.Items[1].IsDisposed.Should().BeFalse(); + disposableValueFactory.Items[2].IsDisposed.Should().BeFalse(); disposableValueFactory.Items[3].IsDisposed.Should().BeFalse(); disposableValueFactory.Items[4].IsDisposed.Should().BeFalse(); disposableValueFactory.Items[5].IsDisposed.Should().BeFalse(); @@ -598,8 +597,8 @@ public void WhenValueEvictedItemRemovedEventIsFired() removedItems.Count.Should().Be(2); - removedItems[0].Key.Should().Be(3); - removedItems[0].Value.Should().Be(4); + removedItems[0].Key.Should().Be(1); + removedItems[0].Value.Should().Be(2); removedItems[0].Reason.Should().Be(ItemRemovedReason.Evicted); removedItems[1].Key.Should().Be(4); @@ -1016,6 +1015,8 @@ public void WhenTrimCountIsMoreThanCapacityThrows() [InlineData(9, new int[] { })] public void WhenColdItemsExistTrimRemovesExpectedItemCount(int trimCount, int[] expected) { + Warmup(); + // initial state: // Hot = 9, 8, 7 // Warm = 3, 2, 1 @@ -1109,6 +1110,8 @@ public void WhenHotItemsExistTrimRemovesExpectedItemCount(int itemCount, int[] e [InlineData(9, new int[] { })] public void WhenColdItemsAreTouchedTrimRemovesExpectedItemCount(int trimCount, int[] expected) { + Warmup(); + // initial state: // Hot = 9, 8, 7 // Warm = 3, 2, 1 diff --git a/BitFaster.Caching.UnitTests/Lru/ConcurrentTLruTests.cs b/BitFaster.Caching.UnitTests/Lru/ConcurrentTLruTests.cs index 16822234..d12eab39 100644 --- a/BitFaster.Caching.UnitTests/Lru/ConcurrentTLruTests.cs +++ b/BitFaster.Caching.UnitTests/Lru/ConcurrentTLruTests.cs @@ -92,8 +92,8 @@ public void WhenValueEvictedItemRemovedEventIsFired() removedItems.Count.Should().Be(2); - removedItems[0].Key.Should().Be(3); - removedItems[0].Value.Should().Be(4); + removedItems[0].Key.Should().Be(1); + removedItems[0].Value.Should().Be(2); removedItems[0].Reason.Should().Be(ItemRemovedReason.Evicted); removedItems[1].Key.Should().Be(4); diff --git a/BitFaster.Caching/Lru/ConcurrentLruCore.cs b/BitFaster.Caching/Lru/ConcurrentLruCore.cs index 64ed80fa..2955946f 100644 --- a/BitFaster.Caching/Lru/ConcurrentLruCore.cs +++ b/BitFaster.Caching/Lru/ConcurrentLruCore.cs @@ -587,20 +587,14 @@ private void CycleDuringWarmup(int hotCount) if (this.hotQueue.TryDequeue(out var item)) { - // always move to warm until it is full - if (Volatile.Read(ref this.counter.warm) < this.capacity.Warm) - { - // If there is a race, we will potentially add multiple items to warm. Guard by cycling the queue. - int warmCount = this.Move(item, ItemDestination.Warm, ItemRemovedReason.Evicted); - CycleWarm(warmCount); - } - else + int count = this.Move(item, ItemDestination.Warm, ItemRemovedReason.Evicted); + + // if warm is now full, overflow to cold and mark as warm + if (count > this.capacity.Warm) { - // Else mark isWarm and move items to cold. - // If there is a race, we will potentially add multiple items to cold. Guard by cycling the queue. Volatile.Write(ref this.isWarm, true); - int coldCount = this.Move(item, ItemDestination.Cold, ItemRemovedReason.Evicted); - CycleCold(coldCount); + count = LastWarmToCold(); + ConstrainCold(count, ItemRemovedReason.Evicted); } } else