Skip to content

Commit b027a68

Browse files
authored
Eliminate races during LRU warmup (#457)
1 parent 8ac5f56 commit b027a68

File tree

3 files changed

+17
-20
lines changed

3 files changed

+17
-20
lines changed

BitFaster.Caching.UnitTests/Lru/ConcurrentLruTests.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -562,11 +562,10 @@ public void WhenValueExpiresItIsDisposed()
562562
lruOfDisposable.GetOrAdd(i, disposableValueFactory.Create);
563563
}
564564

565-
disposableValueFactory.Items[0].IsDisposed.Should().BeFalse();
566-
disposableValueFactory.Items[1].IsDisposed.Should().BeFalse();
567-
568-
disposableValueFactory.Items[2].IsDisposed.Should().BeTrue();
565+
disposableValueFactory.Items[0].IsDisposed.Should().BeTrue();
569566

567+
disposableValueFactory.Items[1].IsDisposed.Should().BeFalse();
568+
disposableValueFactory.Items[2].IsDisposed.Should().BeFalse();
570569
disposableValueFactory.Items[3].IsDisposed.Should().BeFalse();
571570
disposableValueFactory.Items[4].IsDisposed.Should().BeFalse();
572571
disposableValueFactory.Items[5].IsDisposed.Should().BeFalse();
@@ -598,8 +597,8 @@ public void WhenValueEvictedItemRemovedEventIsFired()
598597

599598
removedItems.Count.Should().Be(2);
600599

601-
removedItems[0].Key.Should().Be(3);
602-
removedItems[0].Value.Should().Be(4);
600+
removedItems[0].Key.Should().Be(1);
601+
removedItems[0].Value.Should().Be(2);
603602
removedItems[0].Reason.Should().Be(ItemRemovedReason.Evicted);
604603

605604
removedItems[1].Key.Should().Be(4);
@@ -1016,6 +1015,8 @@ public void WhenTrimCountIsMoreThanCapacityThrows()
10161015
[InlineData(9, new int[] { })]
10171016
public void WhenColdItemsExistTrimRemovesExpectedItemCount(int trimCount, int[] expected)
10181017
{
1018+
Warmup();
1019+
10191020
// initial state:
10201021
// Hot = 9, 8, 7
10211022
// Warm = 3, 2, 1
@@ -1109,6 +1110,8 @@ public void WhenHotItemsExistTrimRemovesExpectedItemCount(int itemCount, int[] e
11091110
[InlineData(9, new int[] { })]
11101111
public void WhenColdItemsAreTouchedTrimRemovesExpectedItemCount(int trimCount, int[] expected)
11111112
{
1113+
Warmup();
1114+
11121115
// initial state:
11131116
// Hot = 9, 8, 7
11141117
// Warm = 3, 2, 1

BitFaster.Caching.UnitTests/Lru/ConcurrentTLruTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ public void WhenValueEvictedItemRemovedEventIsFired()
9292

9393
removedItems.Count.Should().Be(2);
9494

95-
removedItems[0].Key.Should().Be(3);
96-
removedItems[0].Value.Should().Be(4);
95+
removedItems[0].Key.Should().Be(1);
96+
removedItems[0].Value.Should().Be(2);
9797
removedItems[0].Reason.Should().Be(ItemRemovedReason.Evicted);
9898

9999
removedItems[1].Key.Should().Be(4);

BitFaster.Caching/Lru/ConcurrentLruCore.cs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -587,20 +587,14 @@ private void CycleDuringWarmup(int hotCount)
587587

588588
if (this.hotQueue.TryDequeue(out var item))
589589
{
590-
// always move to warm until it is full
591-
if (Volatile.Read(ref this.counter.warm) < this.capacity.Warm)
592-
{
593-
// If there is a race, we will potentially add multiple items to warm. Guard by cycling the queue.
594-
int warmCount = this.Move(item, ItemDestination.Warm, ItemRemovedReason.Evicted);
595-
CycleWarm(warmCount);
596-
}
597-
else
590+
int count = this.Move(item, ItemDestination.Warm, ItemRemovedReason.Evicted);
591+
592+
// if warm is now full, overflow to cold and mark as warm
593+
if (count > this.capacity.Warm)
598594
{
599-
// Else mark isWarm and move items to cold.
600-
// If there is a race, we will potentially add multiple items to cold. Guard by cycling the queue.
601595
Volatile.Write(ref this.isWarm, true);
602-
int coldCount = this.Move(item, ItemDestination.Cold, ItemRemovedReason.Evicted);
603-
CycleCold(coldCount);
596+
count = LastWarmToCold();
597+
ConstrainCold(count, ItemRemovedReason.Evicted);
604598
}
605599
}
606600
else

0 commit comments

Comments
 (0)