11using System ;
2-
3- #if ! NETSTANDARD2_0
4- using System . Buffers ;
5- #endif
6-
7- #if DEBUG
8- using System . Linq ;
9- using System . Text ;
10- #endif
11-
122using System . Collections ;
133using System . Collections . Concurrent ;
144using System . Collections . Generic ;
2212using BitFaster . Caching . Lru ;
2313using BitFaster . Caching . Scheduler ;
2414
15+ #if ! NETSTANDARD2_0
16+ using System . Buffers ;
17+ #endif
18+
19+ #if DEBUG
20+ using System . Linq ;
21+ using System . Text ;
22+ #endif
23+
2524namespace BitFaster . Caching . Lfu
2625{
2726 /// <summary>
@@ -58,7 +57,7 @@ public sealed class ConcurrentLfu<K, V> : ICache<K, V>, IAsyncCache<K, V>, IBoun
5857 private readonly IScheduler scheduler ;
5958
6059#if NETSTANDARD2_0
61- private readonly LfuNode < K , V > [ ] localDrainBuffer ;
60+ private readonly LfuNode < K , V > [ ] drainBuffer ;
6261#endif
6362
6463 public ConcurrentLfu ( int capacity )
@@ -84,7 +83,7 @@ public ConcurrentLfu(int concurrencyLevel, int capacity, IScheduler scheduler, I
8483 this . scheduler = scheduler ;
8584
8685#if NETSTANDARD2_0
87- this . localDrainBuffer = new LfuNode < K , V > [ this . readBuffer . Capacity ] ;
86+ this . drainBuffer = new LfuNode < K , V > [ this . readBuffer . Capacity ] ;
8887#endif
8988 }
9089
@@ -378,35 +377,22 @@ private void DrainBuffers()
378377 private bool Maintenance ( LfuNode < K , V > droppedWrite = null )
379378 {
380379 this . drainStatus . Set ( DrainStatus . ProcessingToIdle ) ;
380+ var localDrainBuffer = RentDrainBuffer ( ) ;
381381
382- bool wasDrained = false ;
383-
384- #if ! NETSTANDARD2_0
385- var localDrainBuffer = ArrayPool < LfuNode < K , V > > . Shared . Rent ( this . readBuffer . Capacity ) ;
386- #endif
387- int maxSweeps = 1 ;
388- int count = 0 ;
382+ // extract to a buffer before doing book keeping work, ~2x faster
383+ var count = readBuffer . DrainTo ( localDrainBuffer ) ;
389384
390- for ( int s = 0 ; s < maxSweeps ; s ++ )
385+ for ( int i = 0 ; i < count ; i ++ )
391386 {
392- count = 0 ;
393-
394- // extract to a buffer before doing book keeping work, ~2x faster
395- count = this . readBuffer . DrainTo ( localDrainBuffer ) ;
396-
397- for ( int i = 0 ; i < count ; i ++ )
398- {
399- this . cmSketch . Increment ( localDrainBuffer [ i ] . Key ) ;
400- }
401-
402- for ( int i = 0 ; i < count ; i ++ )
403- {
404- OnAccess ( localDrainBuffer [ i ] ) ;
405- }
387+ this . cmSketch . Increment ( localDrainBuffer [ i ] . Key ) ;
388+ }
406389
407- wasDrained = count == 0 ;
390+ for ( int i = 0 ; i < count ; i ++ )
391+ {
392+ OnAccess ( localDrainBuffer [ i ] ) ;
408393 }
409394
395+ var wasDrained = count == 0 ;
410396 count = this . writeBuffer . DrainTo ( localDrainBuffer ) ;
411397
412398 for ( int i = 0 ; i < count ; i ++ )
@@ -419,9 +405,7 @@ private bool Maintenance(LfuNode<K, V> droppedWrite = null)
419405 OnWrite ( droppedWrite ) ;
420406 }
421407
422- #if ! NETSTANDARD2_0
423- ArrayPool < LfuNode < K , V > > . Shared . Return ( localDrainBuffer ) ;
424- #endif
408+ ReturnDrainBuffer ( localDrainBuffer ) ;
425409
426410 EvictEntries ( ) ;
427411 this . capacity . OptimizePartitioning ( this . metrics , this . cmSketch . ResetSampleSize ) ;
@@ -642,6 +626,22 @@ private void ReFitProtected()
642626 }
643627 }
644628
629+ private LfuNode < K , V > [ ] RentDrainBuffer ( )
630+ {
631+ #if ! NETSTANDARD2_0
632+ return ArrayPool < LfuNode < K , V > > . Shared . Rent ( this . readBuffer . Capacity ) ;
633+ #else
634+ return drainBuffer ;
635+ #endif
636+ }
637+
638+ private void ReturnDrainBuffer ( LfuNode < K , V > [ ] localDrainBuffer )
639+ {
640+ #if ! NETSTANDARD2_0
641+ ArrayPool < LfuNode < K , V > > . Shared . Return ( localDrainBuffer ) ;
642+ #endif
643+ }
644+
645645 [ DebuggerDisplay ( "{Format(),nq}" ) ]
646646 private class DrainStatus
647647 {
0 commit comments