diff --git a/BitFaster.Caching/Lru/ConcurrentLruCore.cs b/BitFaster.Caching/Lru/ConcurrentLruCore.cs index ac35e27d..5c330467 100644 --- a/BitFaster.Caching/Lru/ConcurrentLruCore.cs +++ b/BitFaster.Caching/Lru/ConcurrentLruCore.cs @@ -513,40 +513,59 @@ private void TrimLiveItems(int itemsRemoved, int itemCount, ItemRemovedReason re int trimWarmAttempts = 0; int maxWarmHotAttempts = (this.capacity.Warm * 2) + this.capacity.Hot; + int warmCount = Volatile.Read(ref this.counter.warm); + int coldCount = Volatile.Read(ref this.counter.cold); + while (itemsRemoved < itemCount && trimWarmAttempts < maxWarmHotAttempts) { - if (Volatile.Read(ref this.counter.cold) > 0) + if (coldCount > 0) { if (TryRemoveCold(reason) == (ItemDestination.Remove, 0)) { itemsRemoved++; + coldCount--; trimWarmAttempts = 0; } - TrimWarmOrHot(reason); + TrimWarmOrHot(reason, ref warmCount, ref coldCount); } else { - TrimWarmOrHot(reason); + TrimWarmOrHot(reason, ref warmCount, ref coldCount); trimWarmAttempts++; } } - if (Volatile.Read(ref this.counter.warm) < this.capacity.Warm) + if (warmCount < this.capacity.Warm) { Volatile.Write(ref this.isWarm, false); } } - private void TrimWarmOrHot(ItemRemovedReason reason) + private void TrimWarmOrHot(ItemRemovedReason reason, ref int warmCount, ref int coldCount) { - if (Volatile.Read(ref this.counter.warm) > 0) + if (warmCount > 0) { - CycleWarmUnchecked(reason); + var (dest, count) = CycleWarmUnchecked(reason); + warmCount--; + UpdateCount(ref warmCount, ref coldCount, dest, count); } else if (Volatile.Read(ref this.counter.hot) > 0) { - CycleHotUnchecked(reason); + var (dest, count) = CycleHotUnchecked(reason); + UpdateCount(ref warmCount, ref coldCount, dest, count); + } + + void UpdateCount(ref int warmCount, ref int coldCount, ItemDestination dest, int count) + { + if (dest == ItemDestination.Cold) + { + coldCount = count; + } + else if (dest == ItemDestination.Warm) + { + warmCount = count; + } } }