Skip to content

Commit 7df400b

Browse files
committed
Simplify BG evictor code and add possibility to wakeup it
1 parent 1b4a986 commit 7df400b

16 files changed

+83
-186
lines changed

cachelib/allocator/BackgroundEvictor-inl.h

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -27,67 +27,61 @@ BackgroundEvictor<CacheT>::BackgroundEvictor(Cache& cache,
2727
: cache_(cache),
2828
strategy_(strategy),
2929
tid_(tid) {
30-
3130
}
3231

3332
template <typename CacheT>
3433
BackgroundEvictor<CacheT>::~BackgroundEvictor() { stop(std::chrono::seconds(0)); }
3534

3635
template <typename CacheT>
3736
void BackgroundEvictor<CacheT>::work() {
38-
if (strategy_->poll_) {
39-
try {
37+
try {
38+
if (!tasks_.empty()) {
39+
while (!tasks_.empty()) {
40+
auto [pid, cid] = tasks_.dequeue();
41+
auto batch = strategy_->calculateBatchSize(cache_, tid_, pid, cid);
42+
auto evicted = BackgroundEvictorAPIWrapper<CacheT>::traverseAndEvictItems(cache_,
43+
tid_,pid,cid,batch);
44+
numEvictedItemsFromSchedule_.fetch_add(1, std::memory_order_relaxed);
45+
runCount_.fetch_add(1, std::memory_order_relaxed);
46+
}
47+
} else {
4048
for (const auto pid : cache_.getRegularPoolIds()) {
4149
//check if the pool is full - probably should be if tier is full
4250
if (cache_.getPoolByTid(pid,tid_).allSlabsAllocated()) {
4351
checkAndRun(pid);
4452
}
4553
}
46-
} catch (const std::exception& ex) {
47-
XLOGF(ERR, "BackgroundEvictor interrupted due to exception: {}", ex.what());
4854
}
49-
} else {
50-
//when an eviction for a given pid,cid at tier 0 is triggered this will be run
51-
while (1) {
52-
std::pair p = tasks_.dequeue();
53-
unsigned int pid = p.first;
54-
unsigned int cid = p.second;
55-
unsigned int batch = strategy_->calculateBatchSize(cache_,tid_,pid,cid);
56-
//try evicting BATCH items from the class in order to reach free target
57-
unsigned int evicted =
58-
BackgroundEvictorAPIWrapper<CacheT>::traverseAndEvictItems(cache_,
59-
tid_,pid,cid,batch);
60-
runCount_ = runCount_ + 1;
61-
}
62-
55+
} catch (const std::exception& ex) {
56+
XLOGF(ERR, "BackgroundEvictor interrupted due to exception: {}", ex.what());
6357
}
6458
}
6559

66-
6760
// Look for classes that exceed the target memory capacity
6861
// and return those for eviction
6962
template <typename CacheT>
70-
void BackgroundEvictor<CacheT>::checkAndRun(PoolId pid) {
71-
63+
void BackgroundEvictor<CacheT>::checkAndRun(PoolId pid) {
7264
const auto& mpStats = cache_.getPoolByTid(pid,tid_).getStats();
7365
for (auto& cid : mpStats.classIds) {
74-
if (strategy_->shouldEvict(cache_,tid_,pid,cid)) {
75-
unsigned int batch = strategy_->calculateBatchSize(cache_,tid_,pid,cid);
76-
//try evicting BATCH items from the class in order to reach free target
77-
unsigned int evicted =
78-
BackgroundEvictorAPIWrapper<CacheT>::traverseAndEvictItems(cache_,
79-
tid_,pid,cid,batch);
80-
numEvictedItems_ += evicted;
81-
}
66+
auto batch = strategy_->calculateBatchSize(cache_,tid_,pid,cid);
67+
if (!batch)
68+
continue;
69+
70+
//try evicting BATCH items from the class in order to reach free target
71+
auto evicted =
72+
BackgroundEvictorAPIWrapper<CacheT>::traverseAndEvictItems(cache_,
73+
tid_,pid,cid,batch);
74+
numEvictedItems_.fetch_add(evicted, std::memory_order_relaxed);
8275
}
83-
runCount_ = runCount_ + 1;
76+
runCount_.fetch_add(1, std::memory_order_relaxed);
8477
}
8578

8679
template <typename CacheT>
8780
BackgroundEvictorStats BackgroundEvictor<CacheT>::getStats() const noexcept {
8881
BackgroundEvictorStats stats;
8982
stats.numEvictedItems = numEvictedItems_.load(std::memory_order_relaxed);
9083
stats.numTraversals = runCount_.load(std::memory_order_relaxed);
84+
stats.numEvictedItemsFromSchedule = numEvictedItemsFromSchedule_.load(std::memory_order_relaxed);
9185
return stats;
9286
}
9387

cachelib/allocator/BackgroundEvictor.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ namespace cachelib {
3232
template <typename C>
3333
struct BackgroundEvictorAPIWrapper {
3434

35-
static unsigned int traverseAndEvictItems(C& cache,
36-
unsigned int tid, unsigned int pid, unsigned int cid, unsigned int batch) {
35+
static size_t traverseAndEvictItems(C& cache,
36+
unsigned int tid, unsigned int pid, unsigned int cid, size_t batch) {
3737
return cache.traverseAndEvictItems(tid,pid,cid,batch);
3838
}
3939
};
@@ -75,6 +75,7 @@ class BackgroundEvictor : public PeriodicWorker {
7575
void checkAndRun(PoolId pid);
7676

7777
std::atomic<uint64_t> numEvictedItems_{0};
78+
std::atomic<uint64_t> numEvictedItemsFromSchedule_{0};
7879
std::atomic<uint64_t> runCount_{0};
7980
};
8081
} // namespace cachelib

cachelib/allocator/BackgroundEvictorStrategy.h

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,10 @@ namespace cachelib {
2626
class BackgroundEvictorStrategy {
2727

2828
public:
29-
30-
BackgroundEvictorStrategy(bool poll) : poll_{poll} {};
31-
32-
virtual unsigned int calculateBatchSize(const CacheBase& cache,
33-
unsigned int tid,
34-
PoolId pid,
35-
ClassId cid ) = 0;
36-
37-
virtual bool shouldEvict(const CacheBase& cache,
29+
virtual size_t calculateBatchSize(const CacheBase& cache,
3830
unsigned int tid,
3931
PoolId pid,
4032
ClassId cid ) = 0;
41-
42-
// if we should poll every n ms or wait for tasks in queue
43-
bool poll_{false};
44-
4533
};
4634

4735
} // namespace cachelib

cachelib/allocator/BackgroundEvictorStrategy.old

Lines changed: 0 additions & 42 deletions
This file was deleted.

cachelib/allocator/CacheAllocator-inl.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,13 @@ CacheAllocator<CacheTrait>::allocateInternalTier(TierId tid,
382382
// Should we support eviction between memory tiers (e.g. from DRAM to PMEM)?
383383
if (memory == nullptr && !config_.disableEviction) {
384384
memory = findEviction(tid, pid, cid);
385-
backgroundEvictor_->schedule(pid,cid);
385+
386+
if (config_.scheduleEviction && backgroundEvictor_) {
387+
backgroundEvictor_->schedule(pid,cid);
388+
if (config_.wakeupBgEvictor) {
389+
backgroundEvictor_->wakeUp();
390+
}
391+
}
386392
}
387393

388394
ItemHandle handle;

cachelib/allocator/CacheAllocator.h

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1769,13 +1769,12 @@ class CacheAllocator : public CacheBase {
17691769

17701770
// exposed for the background evictor to iterate through the memory and evict
17711771
// in batch. This should improve insertion path for tiered memory config
1772-
unsigned int traverseAndEvictItems(unsigned int tid, unsigned int pid, unsigned int cid, unsigned int batch) {
1773-
1772+
size_t traverseAndEvictItems(unsigned int tid, unsigned int pid, unsigned int cid, size_t batch) {
17741773
auto& mmContainer = getMMContainer(tid, pid, cid);
1775-
unsigned int evictions = 0;
1774+
size_t evictions = 0;
17761775
auto itr = mmContainer.getEvictionIterator();
1777-
while (evictions < batch && itr) {
17781776

1777+
while (evictions < batch && itr) {
17791778
Item* candidate = itr.get();
17801779
if (candidate == NULL) {
17811780
break;
@@ -1785,14 +1784,9 @@ class CacheAllocator : public CacheBase {
17851784
// recycles the child we intend to.
17861785

17871786
ItemHandle toReleaseHandle = tryEvictToNextMemoryTier(tid, pid, itr);
1788-
bool movedToNextTier = false;
1789-
if(toReleaseHandle) {
1790-
movedToNextTier = true;
1791-
} else {
1787+
if (!toReleaseHandle) {
17921788
++itr;
1793-
}
1794-
1795-
if (toReleaseHandle) {
1789+
} else {
17961790
if (toReleaseHandle->hasChainedItem()) {
17971791
(*stats_.chainedItemEvictions)[pid][cid].inc();
17981792
} else {
@@ -1817,11 +1811,9 @@ class CacheAllocator : public CacheBase {
18171811
// check if by releasing the item we intend to, we actually
18181812
// recycle the candidate.
18191813
const auto res = releaseBackToAllocator(itemToRelease, RemoveContext::kEviction,
1820-
/* isNascent */ movedToNextTier);
1814+
/* isNascent */ true);
18211815
XDCHECK(res == ReleaseRes::kReleased);
1822-
18231816
}
1824-
18251817
}
18261818

18271819
// Invalidate iterator since later on we may use this mmContainer

cachelib/allocator/CacheAllocatorConfig.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,12 @@ class CacheAllocatorConfig {
597597
// skip promote children items in chained when parent fail to promote
598598
bool skipPromoteChildrenWhenParentFailed{false};
599599

600+
// wakeupBg evictor each time there is no memory to allocate new item in topmost tier
601+
bool wakeupBgEvictor {false};
602+
603+
// every time there is no space to allocate for particual cid,pid pass this information to BG worker
604+
bool scheduleEviction {false};
605+
600606
friend CacheT;
601607

602608
private:

cachelib/allocator/CacheStats.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,9 +287,12 @@ struct ReaperStats {
287287

288288
// Stats for background evictor
289289
struct BackgroundEvictorStats {
290-
// the total number of items the reaper has visited.
290+
// the number of items this worker evicted by looking at pools/classes stats
291291
uint64_t numEvictedItems{0};
292292

293+
// the number of items this worker evicted for pools/classes requested by schedule call
294+
uint64_t numEvictedItemsFromSchedule{0};
295+
293296
// number of times we went executed the thread //TODO: is this def correct?
294297
uint64_t numTraversals{0};
295298

cachelib/allocator/FreeThresholdStrategy.cpp

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -23,39 +23,17 @@ namespace cachelib {
2323

2424

2525

26-
FreeThresholdStrategy::FreeThresholdStrategy(double freeThreshold, bool poll)
27-
: BackgroundEvictorStrategy(poll), freeThreshold_(freeThreshold) {}
26+
FreeThresholdStrategy::FreeThresholdStrategy(double freeThreshold)
27+
: freeThreshold_(freeThreshold) {}
2828

29-
bool FreeThresholdStrategy::shouldEvict(const CacheBase& cache,
29+
size_t FreeThresholdStrategy::calculateBatchSize(const CacheBase& cache,
3030
unsigned int tid,
3131
PoolId pid,
3232
ClassId cid ) {
33-
34-
const auto& mpStats = cache.getPoolByTid(pid,tid).getStats();
35-
size_t allocSize = mpStats.acStats.at(cid).allocSize;
36-
size_t totalMem = mpStats.acStats.at(cid).getTotalMemory() / allocSize;
37-
if (totalMem > 0) {
38-
size_t freeMem = mpStats.acStats.at(cid).getTotalFreeMemory() / allocSize;
39-
return ((double)freeMem / (double)totalMem) < freeThreshold_;
40-
}
41-
return false;
42-
43-
}
44-
45-
unsigned int FreeThresholdStrategy::calculateBatchSize(const CacheBase& cache,
46-
unsigned int tid,
47-
PoolId pid,
48-
ClassId cid ) {
49-
const auto& mpStats = cache.getPoolByTid(pid,tid).getStats();
50-
size_t totalMem = mpStats.acStats.at(cid).getTotalMemory();
51-
size_t freeMem = mpStats.acStats.at(cid).getTotalFreeMemory();
52-
53-
size_t targetMem = (freeThreshold_ * totalMem) - freeMem;
54-
unsigned int batch = (targetMem / mpStats.acStats.at(cid).allocSize);
55-
56-
return batch;
33+
const auto& mpStats = cache.getPoolByTid(pid,tid).getStats().acStats.at(cid);
34+
size_t targetMem = (freeThreshold_ * mpStats.getTotalMemory()) - mpStats.getTotalFreeMemory();
35+
return std::max(0UL, targetMem / mpStats.allocSize);
5736
}
5837

59-
6038
} // namespace cachelib
6139
} // namespace facebook

cachelib/allocator/FreeThresholdStrategy.h

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,26 +27,15 @@ namespace cachelib {
2727
class FreeThresholdStrategy : public BackgroundEvictorStrategy {
2828

2929
public:
30-
31-
FreeThresholdStrategy(double freeThreshold, bool poll);
32-
30+
FreeThresholdStrategy(double freeThreshold);
3331
~FreeThresholdStrategy() {}
3432

35-
unsigned int calculateBatchSize(const CacheBase& cache,
36-
unsigned int tid,
37-
PoolId pid,
38-
ClassId cid );
39-
40-
bool shouldEvict(const CacheBase& cache,
33+
size_t calculateBatchSize(const CacheBase& cache,
4134
unsigned int tid,
4235
PoolId pid,
4336
ClassId cid );
44-
4537
private:
46-
4738
double freeThreshold_;
48-
49-
5039
};
5140

5241
} // namespace cachelib

0 commit comments

Comments
 (0)