@@ -329,7 +329,7 @@ void CacheAllocator<CacheTrait>::initWorkers() {
329
329
if (config_.backgroundEvictorEnabled ()) {
330
330
startNewBackgroundEvictor (config_.backgroundEvictorInterval ,
331
331
config_.backgroundEvictorStrategy ,
332
- 0 ); // right now default to tier 0 );
332
+ config_. backgroundEvictorThreads );
333
333
}
334
334
}
335
335
@@ -353,7 +353,7 @@ CacheAllocator<CacheTrait>::allocate(PoolId poolId,
353
353
creationTime = util::getCurrentTimeSec ();
354
354
}
355
355
return allocateInternal (poolId, key, size, creationTime,
356
- ttlSecs == 0 ? 0 : creationTime + ttlSecs);
356
+ ttlSecs == 0 ? 0 : creationTime + ttlSecs, false );
357
357
}
358
358
359
359
template <typename CacheTrait>
@@ -365,14 +365,24 @@ bool CacheAllocator<CacheTrait>::shouldWakeupBgEvictor(TierId tid, PoolId pid, C
365
365
&& acAllocatedPercentage (tid, pid, cid) >= config_.lowEvictionAcWatermark ;
366
366
}
367
367
368
+ template <typename CacheTrait>
369
+ size_t CacheAllocator<CacheTrait>::backgroundEvictorId(TierId tid, PoolId pid, ClassId cid)
370
+ {
371
+ XDCHECK (backgroundEvictor_.size ());
372
+
373
+ // TODO: came up with some better sharding (use some hashing)
374
+ return (tid + pid + cid) % backgroundEvictor_.size ();
375
+ }
376
+
368
377
template <typename CacheTrait>
369
378
typename CacheAllocator<CacheTrait>::ItemHandle
370
379
CacheAllocator<CacheTrait>::allocateInternalTier(TierId tid,
371
380
PoolId pid,
372
381
typename Item::Key key,
373
382
uint32_t size,
374
383
uint32_t creationTime,
375
- uint32_t expiryTime) {
384
+ uint32_t expiryTime,
385
+ bool fromEvictorThread) {
376
386
util::LatencyTracker tracker{stats ().allocateLatency_ };
377
387
378
388
SCOPE_FAIL { stats_.invalidAllocs .inc (); };
@@ -388,8 +398,8 @@ CacheAllocator<CacheTrait>::allocateInternalTier(TierId tid,
388
398
389
399
void * memory = allocator_[tid]->allocate (pid, requiredSize);
390
400
391
- if (backgroundEvictor_ && (memory == nullptr || shouldWakeupBgEvictor (tid, pid, cid))) {
392
- backgroundEvictor_->wakeUp ();
401
+ if (backgroundEvictor_. size () && !fromEvictorThread && (memory == nullptr || shouldWakeupBgEvictor (tid, pid, cid))) {
402
+ backgroundEvictor_[ backgroundEvictorId (tid, pid, cid)] ->wakeUp ();
393
403
}
394
404
395
405
// TODO: Today disableEviction means do not evict from memory (DRAM).
@@ -447,7 +457,11 @@ double CacheAllocator<CacheTrait>::acAllocatedPercentage(TierId tid, PoolId pid,
447
457
{
448
458
const auto &ac = allocator_[tid]->getPool (pid).getAllocationClassFor (cid);
449
459
auto acAllocatedSize = ac.currAllocSize_ .load (std::memory_order_relaxed);
450
- auto acUsableSize = ac.curAllocatedSlabs_ .load (std::memory_order_relaxed);
460
+ auto acUsableSize = ac.curAllocatedSlabs_ .load (std::memory_order_relaxed) * Slab::kSize ;
461
+
462
+ if (acUsableSize == 0 )
463
+ return 0.0 ;
464
+
451
465
return 100.0 * static_cast <double >(acAllocatedSize) / static_cast <double >(acUsableSize);
452
466
}
453
467
@@ -528,9 +542,10 @@ CacheAllocator<CacheTrait>::allocateInternal(PoolId pid,
528
542
typename Item::Key key,
529
543
uint32_t size,
530
544
uint32_t creationTime,
531
- uint32_t expiryTime) {
545
+ uint32_t expiryTime,
546
+ bool fromEvictorThread) {
532
547
auto tid = getTargetTierForItem (pid, key, size, creationTime, expiryTime);
533
- return allocateInternalTier (tid, pid, key, size, creationTime, expiryTime);
548
+ return allocateInternalTier (tid, pid, key, size, creationTime, expiryTime, fromEvictorThread );
534
549
}
535
550
536
551
template <typename CacheTrait>
@@ -1708,8 +1723,7 @@ bool CacheAllocator<CacheTrait>::shouldEvictToNextMemoryTier(
1708
1723
template <typename CacheTrait>
1709
1724
typename CacheAllocator<CacheTrait>::WriteHandle
1710
1725
CacheAllocator<CacheTrait>::tryEvictToNextMemoryTier(
1711
- TierId tid, PoolId pid, Item& item) {
1712
- if (item.isChainedItem ()) return {}; // TODO: We do not support ChainedItem yet
1726
+ TierId tid, PoolId pid, Item& item, bool fromEvictorThread) {
1713
1727
if (item.isExpired ()) return acquire (&item);
1714
1728
1715
1729
TierId nextTier = tid;
@@ -1722,7 +1736,8 @@ CacheAllocator<CacheTrait>::tryEvictToNextMemoryTier(
1722
1736
item.getKey (),
1723
1737
item.getSize (),
1724
1738
item.getCreationTime (),
1725
- item.getExpiryTime ());
1739
+ item.getExpiryTime (),
1740
+ fromEvictorThread);
1726
1741
1727
1742
if (newItemHdl) {
1728
1743
XDCHECK_EQ (newItemHdl->getSize (), item.getSize ());
@@ -1736,10 +1751,10 @@ CacheAllocator<CacheTrait>::tryEvictToNextMemoryTier(
1736
1751
1737
1752
template <typename CacheTrait>
1738
1753
typename CacheAllocator<CacheTrait>::WriteHandle
1739
- CacheAllocator<CacheTrait>::tryEvictToNextMemoryTier(Item& item) {
1754
+ CacheAllocator<CacheTrait>::tryEvictToNextMemoryTier(Item& item, bool fromEvictorThread ) {
1740
1755
auto tid = getTierId (item);
1741
1756
auto pid = allocator_[tid]->getAllocInfo (item.getMemory ()).poolId ;
1742
- return tryEvictToNextMemoryTier (tid, pid, item);
1757
+ return tryEvictToNextMemoryTier (tid, pid, item, fromEvictorThread );
1743
1758
}
1744
1759
1745
1760
template <typename CacheTrait>
@@ -2382,6 +2397,11 @@ PoolId CacheAllocator<CacheTrait>::addPool(
2382
2397
setRebalanceStrategy (pid, std::move (rebalanceStrategy));
2383
2398
setResizeStrategy (pid, std::move (resizeStrategy));
2384
2399
2400
+ if (backgroundEvictor_.size ()) {
2401
+ for (size_t id = 0 ; id < backgroundEvictor_.size (); id++)
2402
+ backgroundEvictor_[id]->setAssignedMemory (getAssignedMemoryToBgEvictor (id));
2403
+ }
2404
+
2385
2405
return pid;
2386
2406
}
2387
2407
@@ -2504,7 +2524,7 @@ std::set<PoolId> CacheAllocator<CacheTrait>::getRegularPoolIds() const {
2504
2524
folly::SharedMutex::ReadHolder r (poolsResizeAndRebalanceLock_);
2505
2525
// TODO - get rid of the duplication - right now, each tier
2506
2526
// holds pool objects with mostly the same info
2507
- return filterCompactCachePools (allocator_[0 ]->getPoolIds ());
2527
+ return filterCompactCachePools (allocator_[currentTier () ]->getPoolIds ());
2508
2528
}
2509
2529
2510
2530
template <typename CacheTrait>
@@ -2868,7 +2888,8 @@ CacheAllocator<CacheTrait>::allocateNewItemForOldItem(const Item& oldItem) {
2868
2888
oldItem.getKey (),
2869
2889
oldItem.getSize (),
2870
2890
oldItem.getCreationTime (),
2871
- oldItem.getExpiryTime ());
2891
+ oldItem.getExpiryTime (),
2892
+ false );
2872
2893
if (!newItemHdl) {
2873
2894
return {};
2874
2895
}
@@ -3001,14 +3022,14 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
3001
3022
template <typename CacheTrait>
3002
3023
typename CacheAllocator<CacheTrait>::ItemHandle
3003
3024
CacheAllocator<CacheTrait>::evictNormalItem(Item& item,
3004
- bool skipIfTokenInvalid) {
3025
+ bool skipIfTokenInvalid, bool fromEvictorThread ) {
3005
3026
XDCHECK (item.isMoving ());
3006
3027
3007
3028
if (item.isOnlyMoving ()) {
3008
3029
return ItemHandle{};
3009
3030
}
3010
3031
3011
- auto evictHandle = tryEvictToNextMemoryTier (item);
3032
+ auto evictHandle = tryEvictToNextMemoryTier (item, fromEvictorThread );
3012
3033
if (evictHandle) return evictHandle;
3013
3034
3014
3035
auto predicate = [](const Item& it) { return it.getRefCount () == 0 ; };
@@ -3811,12 +3832,43 @@ bool CacheAllocator<CacheTrait>::startNewReaper(
3811
3832
return startNewWorker (" Reaper" , reaper_, interval, reaperThrottleConfig);
3812
3833
}
3813
3834
3835
+ template <typename CacheTrait>
3836
+ auto CacheAllocator<CacheTrait>::getAssignedMemoryToBgEvictor(size_t evictorId)
3837
+ {
3838
+ std::vector<std::tuple<TierId, PoolId, ClassId>> asssignedMemory;
3839
+ // TODO: for now, only evict from tier 0
3840
+ for (TierId tid = 0 ; tid < 1 ; tid++) {
3841
+ auto pools = filterCompactCachePools (allocator_[tid]->getPoolIds ());
3842
+ for (const auto pid : pools) {
3843
+ const auto & mpStats = getPoolByTid (pid,tid).getStats ();
3844
+ for (const auto cid : mpStats.classIds ) {
3845
+ if (backgroundEvictorId (tid, pid, cid) == evictorId) {
3846
+ asssignedMemory.emplace_back (tid, pid, cid);
3847
+ }
3848
+ }
3849
+ }
3850
+ }
3851
+ return asssignedMemory;
3852
+ }
3853
+
3814
3854
template <typename CacheTrait>
3815
3855
bool CacheAllocator<CacheTrait>::startNewBackgroundEvictor(
3816
3856
std::chrono::milliseconds interval,
3817
3857
std::shared_ptr<BackgroundEvictorStrategy> strategy,
3818
- unsigned int tid ) {
3819
- return startNewWorker (" BackgroundEvictor" , backgroundEvictor_, interval, strategy, tid);
3858
+ size_t threads) {
3859
+ XDCHECK (threads > 0 );
3860
+ backgroundEvictor_.resize (threads);
3861
+ bool result = true ;
3862
+
3863
+ for (size_t i = 0 ; i < threads; i++) {
3864
+ auto ret = startNewWorker (" BackgroundEvictor" + std::to_string (i), backgroundEvictor_[i], interval, strategy);
3865
+ result = result && ret;
3866
+
3867
+ if (result) {
3868
+ backgroundEvictor_[i]->setAssignedMemory (getAssignedMemoryToBgEvictor (i));
3869
+ }
3870
+ }
3871
+ return result;
3820
3872
}
3821
3873
3822
3874
template <typename CacheTrait>
@@ -3848,8 +3900,13 @@ bool CacheAllocator<CacheTrait>::stopReaper(std::chrono::seconds timeout) {
3848
3900
3849
3901
template <typename CacheTrait>
3850
3902
bool CacheAllocator<CacheTrait>::stopBackgroundEvictor(
3851
- std::chrono::seconds timeout) {
3852
- return stopWorker (" BackgroundEvictor" , backgroundEvictor_, timeout);
3903
+ std::chrono::seconds timeout) {
3904
+ bool result = true ;
3905
+ for (size_t i = 0 ; i < backgroundEvictor_.size (); i++) {
3906
+ auto ret = stopWorker (" BackgroundEvictor" + std::to_string (i), backgroundEvictor_[i], timeout);
3907
+ result = result && ret;
3908
+ }
3909
+ return result;
3853
3910
}
3854
3911
3855
3912
template <typename CacheTrait>
0 commit comments