18
18
19
19
#include " cachelib/allocator/BackgroundMoverStrategy.h"
20
20
#include " cachelib/allocator/CacheStats.h"
21
- #include " cachelib/common/AtomicCounter.h"
22
21
#include " cachelib/common/PeriodicWorker.h"
23
22
24
23
namespace facebook ::cachelib {
@@ -51,6 +50,7 @@ enum class MoverDir { Evict = 0, Promote };
51
50
template <typename CacheT>
52
51
class BackgroundMover : public PeriodicWorker {
53
52
public:
53
+ using ClassBgStatsType = std::map<MemoryDescriptorType,uint64_t >;
54
54
using Cache = CacheT;
55
55
// @param cache the cache interface
56
56
// @param strategy the stragey class that defines how objects are
@@ -62,8 +62,9 @@ class BackgroundMover : public PeriodicWorker {
62
62
~BackgroundMover () override ;
63
63
64
64
BackgroundMoverStats getStats () const noexcept ;
65
- std::map<TierId, std::map<PoolId, std::map<ClassId, uint64_t >>>
66
- getClassStats () const noexcept ;
65
+ ClassBgStatsType getClassStats () const noexcept {
66
+ return movesPerClass_;
67
+ }
67
68
68
69
void setAssignedMemory (std::vector<MemoryDescriptorType>&& assignedMemory);
69
70
@@ -72,8 +73,27 @@ class BackgroundMover : public PeriodicWorker {
72
73
static size_t workerId (TierId tid, PoolId pid, ClassId cid, size_t numWorkers);
73
74
74
75
private:
75
- std::map<TierId, std::map<PoolId, std::map<ClassId, uint64_t >>>
76
- movesPerClass_;
76
+ ClassBgStatsType movesPerClass_;
77
+
78
+ struct TraversalStats {
79
+ // record a traversal and its time taken
80
+ void recordTraversalTime (uint64_t nsTaken);
81
+
82
+ uint64_t getAvgTraversalTimeNs (uint64_t numTraversals) const ;
83
+ uint64_t getMinTraversalTimeNs () const { return minTraversalTimeNs_; }
84
+ uint64_t getMaxTraversalTimeNs () const { return maxTraversalTimeNs_; }
85
+ uint64_t getLastTraversalTimeNs () const { return lastTraversalTimeNs_; }
86
+
87
+ private:
88
+ // time it took us the last time to traverse the cache.
89
+ uint64_t lastTraversalTimeNs_{0 };
90
+ uint64_t minTraversalTimeNs_{
91
+ std::numeric_limits<uint64_t >::max ()};
92
+ uint64_t maxTraversalTimeNs_{0 };
93
+ uint64_t totalTraversalTimeNs_{0 };
94
+ };
95
+
96
+ TraversalStats traversalStats_;
77
97
// cache allocator's interface for evicting
78
98
using Item = typename Cache::Item;
79
99
@@ -89,9 +109,10 @@ class BackgroundMover : public PeriodicWorker {
89
109
void work () override final ;
90
110
void checkAndRun ();
91
111
92
- AtomicCounter numMovedItems_{0 };
93
- AtomicCounter numTraversals_{0 };
94
- AtomicCounter totalBytesMoved_{0 };
112
+ uint64_t numMovedItems{0 };
113
+ uint64_t numTraversals{0 };
114
+ uint64_t totalClasses{0 };
115
+ uint64_t totalBytesMoved{0 };
95
116
96
117
std::vector<MemoryDescriptorType> assignedMemory_;
97
118
folly::DistributedMutex mutex_;
@@ -111,6 +132,20 @@ BackgroundMover<CacheT>::BackgroundMover(
111
132
}
112
133
}
113
134
135
+ template <typename CacheT>
136
+ void BackgroundMover<CacheT>::TraversalStats::recordTraversalTime(uint64_t nsTaken) {
137
+ lastTraversalTimeNs_ = nsTaken;
138
+ minTraversalTimeNs_ = std::min (minTraversalTimeNs_, nsTaken);
139
+ maxTraversalTimeNs_ = std::max (maxTraversalTimeNs_, nsTaken);
140
+ totalTraversalTimeNs_ += nsTaken;
141
+ }
142
+
143
+ template <typename CacheT>
144
+ uint64_t BackgroundMover<CacheT>::TraversalStats::getAvgTraversalTimeNs(
145
+ uint64_t numTraversals) const {
146
+ return numTraversals ? totalTraversalTimeNs_ / numTraversals : 0 ;
147
+ }
148
+
114
149
template <typename CacheT>
115
150
BackgroundMover<CacheT>::~BackgroundMover () {
116
151
stop (std::chrono::seconds (0 ));
@@ -144,44 +179,56 @@ template <typename CacheT>
144
179
void BackgroundMover<CacheT>::checkAndRun() {
145
180
auto assignedMemory = mutex_.lock_combine ([this ] { return assignedMemory_; });
146
181
147
- unsigned int moves = 0 ;
148
- auto batches = strategy_->calculateBatchSizes (cache_, assignedMemory);
149
-
150
- for (size_t i = 0 ; i < batches.size (); i++) {
151
- const auto [tid, pid, cid] = assignedMemory[i];
152
- const auto batch = batches[i];
182
+ while (true ) {
183
+ unsigned int moves = 0 ;
184
+ std::set<ClassId> classes{};
185
+ auto batches = strategy_->calculateBatchSizes (cache_, assignedMemory);
186
+
187
+ const auto begin = util::getCurrentTimeNs ();
188
+ for (size_t i = 0 ; i < batches.size (); i++) {
189
+ const auto [tid, pid, cid] = assignedMemory[i];
190
+ const auto batch = batches[i];
191
+ if (!batch) {
192
+ continue ;
193
+ }
194
+
195
+ // try moving BATCH items from the class in order to reach free target
196
+ auto moved = moverFunc (cache_, tid, pid, cid, batch);
197
+ moves += moved;
198
+ movesPerClass_[assignedMemory[i]] += moved;
199
+ }
200
+ auto end = util::getCurrentTimeNs ();
201
+ if (moves > 0 ) {
202
+ traversalStats_.recordTraversalTime (end > begin ? end - begin : 0 );
203
+ numMovedItems += moves;
204
+ numTraversals++;
205
+ }
153
206
154
- if (batch == 0 ) {
155
- continue ;
207
+ // we didn't move any objects done with this run
208
+ if (moves == 0 || shouldStopWork ()) {
209
+ break ;
156
210
}
157
- const auto & mpStats = cache_.getPoolByTid (pid, tid).getStats ();
158
- // try moving BATCH items from the class in order to reach free target
159
- auto moved = moverFunc (cache_, tid, pid, cid, batch);
160
- moves += moved;
161
- movesPerClass_[tid][pid][cid] += moved;
162
- totalBytesMoved_.add (moved * mpStats.acStats .at (cid).allocSize );
163
211
}
164
-
165
- numTraversals_.inc ();
166
- numMovedItems_.add (moves);
167
212
}
168
213
169
214
template <typename CacheT>
170
215
BackgroundMoverStats BackgroundMover<CacheT>::getStats() const noexcept {
171
216
BackgroundMoverStats stats;
172
- stats.numMovedItems = numMovedItems_.get ();
173
- stats.runCount = numTraversals_.get ();
174
- stats.totalBytesMoved = totalBytesMoved_.get ();
217
+ stats.numMovedItems = numMovedItems;
218
+ stats.totalBytesMoved = totalBytesMoved;
219
+ stats.totalClasses = totalClasses;
220
+ auto runCount = getRunCount ();
221
+ stats.runCount = runCount;
222
+ stats.numTraversals = numTraversals;
223
+ stats.avgItemsMoved = (double ) stats.numMovedItems / (double )runCount;
224
+ stats.lastTraversalTimeNs = traversalStats_.getLastTraversalTimeNs ();
225
+ stats.avgTraversalTimeNs = traversalStats_.getAvgTraversalTimeNs (numTraversals);
226
+ stats.minTraversalTimeNs = traversalStats_.getMinTraversalTimeNs ();
227
+ stats.maxTraversalTimeNs = traversalStats_.getMaxTraversalTimeNs ();
175
228
176
229
return stats;
177
230
}
178
231
179
- template <typename CacheT>
180
- std::map<TierId, std::map<PoolId, std::map<ClassId, uint64_t >>>
181
- BackgroundMover<CacheT>::getClassStats() const noexcept {
182
- return movesPerClass_;
183
- }
184
-
185
232
template <typename CacheT>
186
233
size_t BackgroundMover<CacheT>::workerId(TierId tid,
187
234
PoolId pid,
0 commit comments