diff --git a/BitFaster.Caching/Lfu/ConcurrentLfu.cs b/BitFaster.Caching/Lfu/ConcurrentLfu.cs index 5913b827..81f7ec8f 100644 --- a/BitFaster.Caching/Lfu/ConcurrentLfu.cs +++ b/BitFaster.Caching/Lfu/ConcurrentLfu.cs @@ -1,14 +1,4 @@ using System; - -#if !NETSTANDARD2_0 -using System.Buffers; -#endif - -#if DEBUG -using System.Linq; -using System.Text; -#endif - using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; @@ -22,6 +12,15 @@ using BitFaster.Caching.Lru; using BitFaster.Caching.Scheduler; +#if !NETSTANDARD2_0 +using System.Buffers; +#endif + +#if DEBUG +using System.Linq; +using System.Text; +#endif + namespace BitFaster.Caching.Lfu { /// @@ -58,7 +57,7 @@ public sealed class ConcurrentLfu : ICache, IAsyncCache, IBoun private readonly IScheduler scheduler; #if NETSTANDARD2_0 - private readonly LfuNode[] localDrainBuffer; + private readonly LfuNode[] drainBuffer; #endif public ConcurrentLfu(int capacity) @@ -84,7 +83,7 @@ public ConcurrentLfu(int concurrencyLevel, int capacity, IScheduler scheduler, I this.scheduler = scheduler; #if NETSTANDARD2_0 - this.localDrainBuffer = new LfuNode[this.readBuffer.Capacity]; + this.drainBuffer = new LfuNode[this.readBuffer.Capacity]; #endif } @@ -378,35 +377,22 @@ private void DrainBuffers() private bool Maintenance(LfuNode droppedWrite = null) { this.drainStatus.Set(DrainStatus.ProcessingToIdle); + var localDrainBuffer = RentDrainBuffer(); - bool wasDrained = false; - -#if !NETSTANDARD2_0 - var localDrainBuffer = ArrayPool>.Shared.Rent(this.readBuffer.Capacity); -#endif - int maxSweeps = 1; - int count = 0; + // extract to a buffer before doing book keeping work, ~2x faster + var count = readBuffer.DrainTo(localDrainBuffer); - for (int s = 0; s < maxSweeps; s++) + for (int i = 0; i < count; i++) { - count = 0; - - // extract to a buffer before doing book keeping work, ~2x faster - count = this.readBuffer.DrainTo(localDrainBuffer); - - for (int i = 0; i < count; i++) - { - this.cmSketch.Increment(localDrainBuffer[i].Key); - } - - for (int i = 0; i < count; i++) - { - OnAccess(localDrainBuffer[i]); - } + this.cmSketch.Increment(localDrainBuffer[i].Key); + } - wasDrained = count == 0; + for (int i = 0; i < count; i++) + { + OnAccess(localDrainBuffer[i]); } + var wasDrained = count == 0; count = this.writeBuffer.DrainTo(localDrainBuffer); for (int i = 0; i < count; i++) @@ -419,9 +405,7 @@ private bool Maintenance(LfuNode droppedWrite = null) OnWrite(droppedWrite); } -#if !NETSTANDARD2_0 - ArrayPool>.Shared.Return(localDrainBuffer); -#endif + ReturnDrainBuffer(localDrainBuffer); EvictEntries(); this.capacity.OptimizePartitioning(this.metrics, this.cmSketch.ResetSampleSize); @@ -642,6 +626,22 @@ private void ReFitProtected() } } + private LfuNode[] RentDrainBuffer() + { +#if !NETSTANDARD2_0 + return ArrayPool>.Shared.Rent(this.readBuffer.Capacity); +#else + return drainBuffer; +#endif + } + + private void ReturnDrainBuffer(LfuNode[] localDrainBuffer) + { +#if !NETSTANDARD2_0 + ArrayPool>.Shared.Return(localDrainBuffer); +#endif + } + [DebuggerDisplay("{Format(),nq}")] private class DrainStatus {