Skip to content

Commit ea12bd0

Browse files
committed
improved background eviction
1 parent a87ccaa commit ea12bd0

File tree

11 files changed

+220
-121
lines changed

11 files changed

+220
-121
lines changed

cachelib/allocator/BackgroundMover-inl.h

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,22 @@ BackgroundMover<CacheT>::BackgroundMover(
3636
}
3737
}
3838

39+
template <typename CacheT>
40+
void BackgroundMover<CacheT>::TraversalStats::recordTraversalTime(uint64_t msTaken) {
41+
lastTraversalTimeMs_.store(msTaken, std::memory_order_relaxed);
42+
minTraversalTimeMs_.store(std::min(minTraversalTimeMs_.load(), msTaken),
43+
std::memory_order_relaxed);
44+
maxTraversalTimeMs_.store(std::max(maxTraversalTimeMs_.load(), msTaken),
45+
std::memory_order_relaxed);
46+
totalTraversalTimeMs_.fetch_add(msTaken, std::memory_order_relaxed);
47+
}
48+
49+
template <typename CacheT>
50+
uint64_t BackgroundMover<CacheT>::TraversalStats::getAvgTraversalTimeMs(
51+
uint64_t numTraversals) const {
52+
return numTraversals ? totalTraversalTimeMs_ / numTraversals : 0;
53+
}
54+
3955
template <typename CacheT>
4056
BackgroundMover<CacheT>::~BackgroundMover() {
4157
stop(std::chrono::seconds(0));
@@ -73,6 +89,7 @@ void BackgroundMover<CacheT>::checkAndRun() {
7389
std::set<ClassId> classes{};
7490
auto batches = strategy_->calculateBatchSizes(cache_, assignedMemory);
7591

92+
const auto begin = util::getCurrentTimeNs();
7693
//const auto& mpStats = cache_.getPoolByTid(0, 0).getStats();
7794
for (size_t i = 0; i < batches.size(); i++) {
7895
const auto [tid, pid, cid] = assignedMemory[i];
@@ -87,28 +104,39 @@ void BackgroundMover<CacheT>::checkAndRun() {
87104
// try moving BATCH items from the class in order to reach free target
88105
auto moved = moverFunc(cache_, tid, pid, cid, batch);
89106
moves += moved;
90-
moves_per_class_[tid][pid][cid] += moved;
107+
moves_per_class_[assignedMemory[i]] += moved;
91108
//totalBytesMoved.add(moved * mpStats.acStats.at(cid).allocSize);
92109
}
110+
auto end = util::getCurrentTimeNs();
111+
if (moves > 0) {
112+
traversalStats_.recordTraversalTime(end > begin ? end - begin : 0);
113+
numMovedItems.add(moves);
114+
numTraversals.inc();
115+
totalClasses.add(classes.size());
116+
}
93117

94-
numTraversals.inc();
95-
numMovedItems.add(moves);
96-
totalClasses.add(classes.size());
97118
}
98119

99120
template <typename CacheT>
100121
BackgroundMoverStats BackgroundMover<CacheT>::getStats() const noexcept {
101122
BackgroundMoverStats stats;
102123
stats.numMovedItems = numMovedItems.get();
103-
stats.runCount = numTraversals.get();
104124
stats.totalBytesMoved = totalBytesMoved.get();
105125
stats.totalClasses = totalClasses.get();
126+
auto runCount = getRunCount();
127+
stats.runCount = runCount;
128+
stats.numTraversals = numTraversals.get();
129+
stats.avgItemsMoved = (double) stats.numMovedItems / (double)runCount;
130+
stats.lastTraversalTimeMs = traversalStats_.getLastTraversalTimeMs();
131+
stats.avgTraversalTimeMs = traversalStats_.getAvgTraversalTimeMs(runCount);
132+
stats.minTraversalTimeMs = traversalStats_.getMinTraversalTimeMs();
133+
stats.maxTraversalTimeMs = traversalStats_.getMaxTraversalTimeMs();
106134

107135
return stats;
108136
}
109137

110138
template <typename CacheT>
111-
std::map<TierId, std::map<PoolId, std::map<ClassId, uint64_t>>>
139+
std::map<MemoryDescriptorType,uint64_t>
112140
BackgroundMover<CacheT>::getClassStats() const noexcept {
113141
return moves_per_class_;
114142
}

cachelib/allocator/BackgroundMover.h

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,34 @@ class BackgroundMover : public PeriodicWorker {
7474
~BackgroundMover() override;
7575

7676
BackgroundMoverStats getStats() const noexcept;
77-
std::map<TierId, std::map<PoolId, std::map<ClassId, uint64_t>>>
78-
getClassStats() const noexcept;
77+
std::map<MemoryDescriptorType,uint64_t> getClassStats() const noexcept;
7978

8079
void setAssignedMemory(std::vector<MemoryDescriptorType>&& assignedMemory);
8180

8281
private:
83-
std::map<TierId, std::map<PoolId, std::map<ClassId, uint64_t>>>
84-
moves_per_class_;
82+
std::map<MemoryDescriptorType,uint64_t> moves_per_class_;
83+
84+
struct TraversalStats {
85+
// record a traversal and its time taken
86+
void recordTraversalTime(uint64_t msTaken);
87+
88+
uint64_t getAvgTraversalTimeMs(uint64_t numTraversals) const;
89+
uint64_t getMinTraversalTimeMs() const { return minTraversalTimeMs_; }
90+
uint64_t getMaxTraversalTimeMs() const { return maxTraversalTimeMs_; }
91+
uint64_t getLastTraversalTimeMs() const { return lastTraversalTimeMs_; }
92+
uint64_t getNumTraversals() const { return numTraversals_; }
93+
94+
private:
95+
// time it took us the last time to traverse the cache.
96+
std::atomic<uint64_t> lastTraversalTimeMs_{0};
97+
std::atomic<uint64_t> minTraversalTimeMs_{
98+
std::numeric_limits<uint64_t>::max()};
99+
std::atomic<uint64_t> maxTraversalTimeMs_{0};
100+
std::atomic<uint64_t> totalTraversalTimeMs_{0};
101+
std::atomic<uint64_t> numTraversals_{0};
102+
};
103+
104+
TraversalStats traversalStats_;
85105
// cache allocator's interface for evicting
86106
using Item = typename Cache::Item;
87107

cachelib/allocator/BackgroundMoverStrategy.h

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,6 @@
2222
namespace facebook {
2323
namespace cachelib {
2424

25-
struct MemoryDescriptorType {
26-
MemoryDescriptorType(TierId tid, PoolId pid, ClassId cid) :
27-
tid_(tid), pid_(pid), cid_(cid) {}
28-
TierId tid_;
29-
PoolId pid_;
30-
ClassId cid_;
31-
};
3225

3326
// Base class for background eviction strategy.
3427
class BackgroundMoverStrategy {
@@ -38,5 +31,27 @@ class BackgroundMoverStrategy {
3831
std::vector<MemoryDescriptorType> acVec) = 0;
3932
};
4033

34+
class DefaultBackgroundMoverStrategy : public BackgroundMoverStrategy {
35+
public:
36+
DefaultBackgroundMoverStrategy(uint64_t batchSize)
37+
: batchSize_(batchSize) {}
38+
~DefaultBackgroundMoverStrategy() {}
39+
40+
std::vector<size_t> calculateBatchSizes(
41+
const CacheBase& cache,
42+
std::vector<MemoryDescriptorType> acVec) {
43+
std::vector<size_t> batches{};
44+
for (auto [tid, pid, cid] : acVec) {
45+
auto stats = cache.getACStats(tid, pid, cid);
46+
if (stats.usageFraction() > 0.90) {
47+
batches.push_back(batchSize_);
48+
}
49+
}
50+
return batches;
51+
}
52+
private:
53+
uint64_t batchSize_{100};
54+
};
55+
4156
} // namespace cachelib
4257
} // namespace facebook

cachelib/allocator/Cache.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,38 @@ enum class DestructorContext {
7373
kRemovedFromNVM
7474
};
7575

76+
struct MemoryDescriptorType {
77+
MemoryDescriptorType(TierId tid, PoolId pid, ClassId cid) :
78+
tid_(tid), pid_(pid), cid_(cid) {}
79+
TierId tid_;
80+
PoolId pid_;
81+
ClassId cid_;
82+
83+
bool operator<(const MemoryDescriptorType& rhs) {
84+
if (this->tid_ <= rhs.tid_) {
85+
if (this->pid_ <= rhs.pid_) {
86+
if (this->cid_ < rhs.cid_) return true;
87+
else return false;
88+
}
89+
return false;
90+
}
91+
return false;
92+
}
93+
94+
friend bool operator<(const MemoryDescriptorType& lhs, const MemoryDescriptorType& rhs);
95+
};
96+
97+
inline bool operator<(const MemoryDescriptorType& lhs, const MemoryDescriptorType& rhs) {
98+
if (lhs.tid_ <= rhs.tid_) {
99+
if (lhs.pid_ <= rhs.pid_) {
100+
if (lhs.cid_ < rhs.cid_) return true;
101+
else return false;
102+
}
103+
return false;
104+
}
105+
return false;
106+
}
107+
76108
// A base class of cache exposing members and status agnostic of template type.
77109
class CacheBase {
78110
public:

cachelib/allocator/CacheAllocator.h

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,42 +1188,37 @@ class CacheAllocator : public CacheBase {
11881188
return stats;
11891189
}
11901190

1191-
// returns the background mover stats
1192-
BackgroundMoverStats getBackgroundMoverStats(MoverDir direction) const {
1193-
auto stats = BackgroundMoverStats{};
1191+
// returns the background mover stats per thread
1192+
std::vector<BackgroundMoverStats> getBackgroundMoverStats(MoverDir direction) const {
1193+
auto stats = std::vector<BackgroundMoverStats>();
11941194
if (direction == MoverDir::Evict) {
11951195
for (auto& bg : backgroundEvictor_)
1196-
stats += bg->getStats();
1196+
stats.push_back(bg->getStats());
11971197
} else if (direction == MoverDir::Promote) {
11981198
for (auto& bg : backgroundPromoter_)
1199-
stats += bg->getStats();
1199+
stats.push_back(bg->getStats());
12001200
}
12011201
return stats;
12021202
}
12031203

1204-
std::map<TierId, std::map<PoolId, std::map<ClassId, uint64_t>>>
1204+
std::map<MemoryDescriptorType,uint64_t>
12051205
getBackgroundMoverClassStats(MoverDir direction) const {
1206-
std::map<TierId, std::map<PoolId, std::map<ClassId, uint64_t>>> stats;
1206+
std::map<MemoryDescriptorType,uint64_t> stats;
1207+
auto record = [&](auto &bg) {
1208+
//gives a unique descriptor
1209+
auto classStats = bg->getClassStats();
1210+
for (const auto& [key,value] : classStats) {
1211+
stats[key] = value;
1212+
}
1213+
};
12071214

12081215
if (direction == MoverDir::Evict) {
12091216
for (auto& bg : backgroundEvictor_) {
1210-
for (auto& tid : bg->getClassStats()) {
1211-
for (auto& pid : tid.second) {
1212-
for (auto& cid : pid.second) {
1213-
stats[tid.first][pid.first][cid.first] += cid.second;
1214-
}
1215-
}
1216-
}
1217+
record(bg);
12171218
}
12181219
} else if (direction == MoverDir::Promote) {
12191220
for (auto& bg : backgroundPromoter_) {
1220-
for (auto& tid : bg->getClassStats()) {
1221-
for (auto& pid : tid.second) {
1222-
for (auto& cid : pid.second) {
1223-
stats[tid.first][pid.first][cid.first] += cid.second;
1224-
}
1225-
}
1226-
}
1221+
record(bg);
12271222
}
12281223
}
12291224

@@ -2253,8 +2248,13 @@ auto& mmContainer = getMMContainer(tid, pid, cid);
22532248
newItemHandles[index]->getSize());
22542249
(*stats_.dsaEvictionSubmits)[tid][pid][cid].inc();
22552250
if (config_.dsaAsync) {
2256-
dmlHandles.emplace_back(
2257-
dml::submit<dml::hardware>(dml::mem_copy, srcView, dstView));
2251+
if (cid < 11) {
2252+
dmlHandles.emplace_back(
2253+
dml::submit<dml::software>(dml::mem_copy, srcView, dstView));
2254+
} else {
2255+
dmlHandles.emplace_back(
2256+
dml::submit<dml::hardware>(dml::mem_copy, srcView, dstView));
2257+
}
22582258
} else {
22592259
auto dmlHandle = dml::submit<dml::hardware>(dml::mem_copy, srcView, dstView);
22602260
auto result = dmlHandle.get();
@@ -2804,7 +2804,9 @@ auto& mmContainer = getMMContainer(tid, pid, cid);
28042804
// free memory monitor
28052805
std::unique_ptr<MemoryMonitor> memMonitor_;
28062806

2807-
// background evictor
2807+
// background data movement
2808+
2809+
28082810
std::vector<std::unique_ptr<BackgroundMover<CacheT>>> backgroundEvictor_;
28092811
std::vector<std::unique_ptr<BackgroundMover<CacheT>>> backgroundPromoter_;
28102812

cachelib/allocator/CacheStats.h

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -311,18 +311,34 @@ struct BackgroundMoverStats {
311311
uint64_t numMovedItems{0};
312312
// number of times we went executed the thread //TODO: is this def correct?
313313
uint64_t runCount{0};
314+
315+
double avgItemsMoved{0.0};
316+
317+
uint64_t numTraversals{0};
314318
// total number of classes
315319
uint64_t totalClasses{0};
316320
// eviction size
317321
uint64_t totalBytesMoved{0};
322+
323+
// indicates the time in ms for the last iteration across the entire cache
324+
uint64_t lastTraversalTimeMs{0};
318325

319-
BackgroundMoverStats& operator+=(const BackgroundMoverStats& rhs) {
320-
numMovedItems += rhs.numMovedItems;
321-
runCount += rhs.runCount;
322-
totalClasses += rhs.totalClasses;
323-
totalBytesMoved += rhs.totalBytesMoved;
324-
return *this;
325-
}
326+
// indicates the maximum of all traversals
327+
uint64_t minTraversalTimeMs{0};
328+
329+
// indicates the minimum of all traversals
330+
uint64_t maxTraversalTimeMs{0};
331+
332+
// indicates the average of all traversals
333+
uint64_t avgTraversalTimeMs{0};
334+
335+
//BackgroundMoverStats& operator+=(const BackgroundMoverStats& rhs) {
336+
// numMovedItems += rhs.numMovedItems;
337+
// runCount += rhs.runCount;
338+
// totalClasses += rhs.totalClasses;
339+
// totalBytesMoved += rhs.totalBytesMoved;
340+
// return *this;
341+
//}
326342
};
327343

328344

@@ -347,9 +363,9 @@ struct Stats;
347363
// the ones that are aggregated over all pools
348364
struct GlobalCacheStats {
349365
// background eviction stats
350-
BackgroundMoverStats evictionStats;
366+
std::vector<BackgroundMoverStats> evictionStats;
351367

352-
BackgroundMoverStats promotionStats;
368+
std::vector<BackgroundMoverStats> promotionStats;
353369

354370
// number of calls to CacheAllocator::find
355371
uint64_t numCacheGets{0};

cachelib/cachebench/cache/Cache-inl.h

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -646,13 +646,15 @@ Stats Cache<Allocator>::getStats() const {
646646
ret.numItems.push_back(aggregate.numItems());
647647
}
648648

649-
std::map<TierId, std::map<PoolId, std::map<ClassId, ACStats>>> allocationClassStats{};
649+
std::map<MemoryDescriptorType, ACStats> allocationClassStats{};
650650

651651
for (size_t pid = 0; pid < pools_.size(); pid++) {
652652
auto cids = cache_->getPoolStats(static_cast<PoolId>(pid)).getClassIds();
653653
for (TierId tid = 0; tid < cache_->getNumTiers(); tid++) {
654-
for (auto cid : cids)
655-
allocationClassStats[tid][pid][cid] = cache_->getACStats(tid, pid, cid);
654+
for (auto cid : cids) {
655+
MemoryDescriptorType md(tid,pid,cid);
656+
allocationClassStats[md] = cache_->getACStats(tid, pid, cid);
657+
}
656658
}
657659
}
658660

@@ -662,19 +664,8 @@ Stats Cache<Allocator>::getStats() const {
662664

663665
ret.allocationClassStats = allocationClassStats;
664666

665-
ret.backgndEvicStats.nEvictedItems =
666-
cacheStats.evictionStats.numMovedItems;
667-
ret.backgndEvicStats.nTraversals =
668-
cacheStats.evictionStats.runCount;
669-
ret.backgndEvicStats.nClasses =
670-
cacheStats.evictionStats.totalClasses;
671-
ret.backgndEvicStats.evictionSize =
672-
cacheStats.evictionStats.totalBytesMoved;
673-
674-
ret.backgndPromoStats.nPromotedItems =
675-
cacheStats.promotionStats.numMovedItems;
676-
ret.backgndPromoStats.nTraversals =
677-
cacheStats.promotionStats.runCount;
667+
ret.backgroundEvictorStats = cacheStats.evictionStats;
668+
ret.backgroundPromoStats = cacheStats.promotionStats;
678669

679670
ret.evictAttempts = cacheStats.evictionAttempts;
680671
ret.dsaEvictionSubmits = cacheStats.dsaEvictionSubmits;

0 commit comments

Comments
 (0)