Skip to content

Commit 9062b5b

Browse files
committed
use approximate usage fraction
1 parent 2307fd9 commit 9062b5b

File tree

10 files changed

+116
-14
lines changed

10 files changed

+116
-14
lines changed

cachelib/allocator/BackgroundMoverStrategy.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,34 @@ class BackgroundMoverStrategy {
3838
virtual ~BackgroundMoverStrategy() = default;
3939
};
4040

41+
class DefaultBackgroundMoverStrategy : public BackgroundMoverStrategy {
42+
public:
43+
DefaultBackgroundMoverStrategy(uint64_t batchSize, double targetFree)
44+
: batchSize_(batchSize), targetFree_((double)targetFree/100.0) {}
45+
~DefaultBackgroundMoverStrategy() {}
46+
47+
std::vector<size_t> calculateBatchSizes(
48+
const CacheBase& cache,
49+
std::vector<MemoryDescriptorType> acVec) {
50+
std::vector<size_t> batches{};
51+
for (auto [tid, pid, cid] : acVec) {
52+
double usage = cache.getPoolByTid(pid, tid).getApproxUsage(cid);
53+
uint32_t perSlab = cache.getPoolByTid(pid, tid).getPerSlab(cid);
54+
if (usage >= (1.0-targetFree_)) {
55+
uint32_t batch = batchSize_ > perSlab ? perSlab : batchSize_;
56+
batches.push_back(batch);
57+
} else {
58+
//no work to be done since there is already
59+
//at least targetFree remaining in the class
60+
batches.push_back(0);
61+
}
62+
}
63+
return batches;
64+
}
65+
private:
66+
uint64_t batchSize_{100};
67+
double targetFree_{0.05};
68+
};
69+
4170
} // namespace cachelib
4271
} // namespace facebook

cachelib/allocator/CacheAllocator-inl.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -401,9 +401,13 @@ CacheAllocator<CacheTrait>::allocate(PoolId poolId,
401401
}
402402

403403
template <typename CacheTrait>
404-
bool CacheAllocator<CacheTrait>::shouldWakeupBgEvictor(TierId tid,
405-
PoolId /* pid */,
406-
ClassId /* cid */) {
404+
bool CacheAllocator<CacheTrait>::shouldWakeupBgEvictor(TierId tid, PoolId pid, ClassId cid) {
405+
// TODO: should we also work on lower tiers? should we have separate set of params?
406+
if (tid == 1) return false;
407+
double usage = getPoolByTid(pid, tid).getApproxUsage(cid);
408+
if (((1-usage)*100) <= config_.lowEvictionAcWatermark) {
409+
return true;
410+
}
407411
return false;
408412
}
409413

cachelib/allocator/FreeThresholdStrategy.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,18 @@ std::vector<size_t> FreeThresholdStrategy::calculateBatchSizes(
3434
std::vector<MemoryDescriptorType> acVec) {
3535
std::vector<size_t> batches{};
3636
for (auto [tid, pid, cid] : acVec) {
37-
auto stats = cache.getACStats(tid, pid, cid);
38-
if ((1-stats.usageFraction())*100 >= highEvictionAcWatermark) {
37+
const auto& pool = cache.getPoolByTid(pid, tid);
38+
if (pool.getApproxFreeSlabs()) {
3939
batches.push_back(0);
40-
} else {
41-
auto toFreeMemPercent = highEvictionAcWatermark - (1-stats.usageFraction())*100;
40+
}
41+
double usage = pool.getApproxUsage(cid);
42+
if ((1-usage)*100 < highEvictionAcWatermark && pool.allSlabsAllocated()) {
43+
auto toFreeMemPercent = highEvictionAcWatermark - (1-usage)*100;
4244
auto toFreeItems = static_cast<size_t>(
43-
toFreeMemPercent * (stats.totalSlabs() * Slab::kSize) / stats.allocSize);
45+
toFreeMemPercent * (pool.getApproxSlabs(cid) * pool.getPerSlab(cid)) );
4446
batches.push_back(toFreeItems);
47+
} else {
48+
batches.push_back(0);
4549
}
4650
}
4751

cachelib/allocator/PromotionStrategy.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,14 @@ class PromotionStrategy : public BackgroundMoverStrategy {
3838
std::vector<size_t> batches{};
3939
for (auto [tid, pid, cid] : acVec) {
4040
XDCHECK(tid > 0);
41-
auto stats = cache.getACStats(tid - 1, pid, cid);
42-
if ((1-stats.usageFraction())*100 < promotionAcWatermark)
41+
const auto& pool = cache.getPoolByTid(pid, tid-1);
42+
double usage = pool.getApproxUsage(cid);
43+
if ((1-usage)*100 <= promotionAcWatermark)
4344
batches.push_back(0);
4445
else {
4546
auto maxPossibleItemsToPromote = static_cast<size_t>(
46-
(promotionAcWatermark - (1-stats.usageFraction())*100) *
47-
(stats.totalSlabs() * Slab::kSize) / stats.allocSize);
47+
( (promotionAcWatermark - (1-usage*100) ) *
48+
(pool.getApproxSlabs(cid) * pool.getPerSlab(cid)) ) );
4849
batches.push_back(maxPossibleItemsToPromote);
4950
}
5051
}

cachelib/allocator/memory/AllocationClass.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,30 @@ ACStats AllocationClass::getStats() const {
704704
});
705705
}
706706

707+
uint32_t AllocationClass::getPerSlab() const {
708+
return getAllocsPerSlab();
709+
}
710+
711+
uint32_t AllocationClass::getApproxSlabs() const {
712+
return allocatedSlabs_.size();
713+
}
714+
715+
double AllocationClass::getApproxUsage() const {
716+
const unsigned long long nSlabsAllocated = allocatedSlabs_.size();
717+
if (nSlabsAllocated == 0) {
718+
return 0.0;
719+
}
720+
const unsigned long long perSlab = getAllocsPerSlab();
721+
const auto freeAllocsInCurrSlab =
722+
canAllocateFromCurrentSlabLocked()
723+
? (Slab::kSize - currOffset_) / allocationSize_
724+
: 0;
725+
const unsigned long long nFreedAllocs = freedAllocations_.size();
726+
const unsigned long long nActiveAllocs =
727+
nSlabsAllocated * perSlab - nFreedAllocs - freeAllocsInCurrSlab;
728+
return (double) nActiveAllocs / (double) (nSlabsAllocated * perSlab);
729+
}
730+
707731
void AllocationClass::createSlabReleaseAllocMapLocked(const Slab* slab) {
708732
// Initialize slab free state
709733
// Each bit represents whether or not an alloc has already been freed

cachelib/allocator/memory/AllocationClass.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,13 @@ class AllocationClass {
9797
// fetch stats about this allocation class.
9898
ACStats getStats() const;
9999

100+
// get approx usage as fraction of used allocs/total allocs in this class
101+
double getApproxUsage() const;
102+
// get approx slabs in this class
103+
uint32_t getApproxSlabs() const;
104+
// get items per slabs in this class
105+
uint32_t getPerSlab() const;
106+
100107
// Whether the pool is full or free to allocate more in the current state.
101108
// This is only a hint and not a gurantee that subsequent allocate will
102109
// fail/succeed.

cachelib/allocator/memory/MemoryAllocatorStats.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ struct ACStats {
7070

7171
return activeAllocs / (usedSlabs * allocsPerSlab);
7272
}
73-
73+
7474
constexpr double approxUsage() const noexcept {
7575
const unsigned long long nSlabsAllocated = usedSlabs;
7676
if (nSlabsAllocated == 0) {

cachelib/allocator/memory/MemoryPool.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,3 +523,22 @@ MPStats MemoryPool::getStats() const {
523523
slabsUnAllocated, nSlabResize_, nSlabRebalance_,
524524
curSlabsAdvised_};
525525
}
526+
527+
double MemoryPool::getApproxUsage(ClassId cid) const {
528+
const auto& ac = getAllocationClassFor(cid);
529+
return ac.getApproxUsage();
530+
}
531+
532+
uint32_t MemoryPool::getApproxFreeSlabs() const {
533+
return freeSlabs_.size();
534+
}
535+
536+
uint32_t MemoryPool::getApproxSlabs(ClassId cid) const {
537+
const auto& ac = getAllocationClassFor(cid);
538+
return ac.getApproxSlabs();
539+
}
540+
541+
uint32_t MemoryPool::getPerSlab(ClassId cid) const {
542+
const auto& ac = getAllocationClassFor(cid);
543+
return ac.getPerSlab();
544+
}

cachelib/allocator/memory/MemoryPool.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,14 @@ class MemoryPool {
132132
}
133133

134134
MPStats getStats() const;
135+
// approx usage fraction per class
136+
double getApproxUsage(ClassId cid) const;
137+
// approx slabs assigned to a given class
138+
uint32_t getApproxSlabs(ClassId cid) const;
139+
140+
uint32_t getApproxFreeSlabs() const;
141+
// items per slab for a class
142+
uint32_t getPerSlab(ClassId cid) const;
135143

136144
// allocates memory of at least _size_ bytes.
137145
//

cachelib/cachebench/util/CacheConfig.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,13 @@ std::shared_ptr<BackgroundMoverStrategy> CacheConfig::getBackgroundEvictorStrate
177177
if (backgroundEvictorIntervalMilSec == 0) {
178178
return nullptr;
179179
}
180-
return std::make_shared<FreeThresholdStrategy>(lowEvictionAcWatermark, highEvictionAcWatermark, maxEvictionBatch, minEvictionBatch);
180+
if (backgroundEvictorStrategy == "threshold") {
181+
return std::make_shared<FreeThresholdStrategy>(lowEvictionAcWatermark, highEvictionAcWatermark, maxEvictionBatch, minEvictionBatch);
182+
} else if (backgroundEvictorStrategy == "fixed") {
183+
return std::make_shared<DefaultBackgroundMoverStrategy>(maxEvictionBatch, highEvictionAcWatermark);
184+
} else {
185+
return std::make_shared<FreeThresholdStrategy>(lowEvictionAcWatermark, highEvictionAcWatermark, maxEvictionBatch, minEvictionBatch);
186+
}
181187
}
182188

183189
std::shared_ptr<BackgroundMoverStrategy> CacheConfig::getBackgroundPromoterStrategy() const {

0 commit comments

Comments
 (0)