Skip to content

Commit 19742ff

Browse files
byrnedjvinser52
authored andcommitted
Per tier pool stats (#70)
1 parent aa8c6be commit 19742ff

File tree

12 files changed

+425
-130
lines changed

12 files changed

+425
-130
lines changed

cachelib/allocator/Cache.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ void CacheBase::updateGlobalCacheStats(const std::string& statPrefix) const {
244244
statPrefix + "cache.size.configured",
245245
memStats.configuredRamCacheSize + memStats.nvmCacheSize);
246246

247+
//TODO: add specific per-tier counters
247248
const auto stats = getGlobalCacheStats();
248249

249250
// Eviction Stats
@@ -253,7 +254,8 @@ void CacheBase::updateGlobalCacheStats(const std::string& statPrefix) const {
253254
// from both ram and nvm, this is counted as a single eviction from cache.
254255
// Ram Evictions: item evicted from ram but it can be inserted into nvm
255256
const std::string ramEvictionKey = statPrefix + "ram.evictions";
256-
counters_.updateDelta(ramEvictionKey, stats.numEvictions);
257+
counters_.updateDelta(ramEvictionKey,
258+
std::accumulate(stats.numEvictions.begin(), stats.numEvictions.end(), 0));
257259
// Nvm Evictions: item evicted from nvm but it can be still in ram
258260
const std::string nvmEvictionKey = statPrefix + "nvm.evictions";
259261
counters_.updateDelta(nvmEvictionKey, stats.numNvmEvictions);
@@ -295,11 +297,11 @@ void CacheBase::updateGlobalCacheStats(const std::string& statPrefix) const {
295297
}
296298

297299
counters_.updateDelta(statPrefix + "cache.alloc_attempts",
298-
stats.allocAttempts);
300+
std::accumulate(stats.allocAttempts.begin(), stats.allocAttempts.end(),0));
299301
counters_.updateDelta(statPrefix + "cache.eviction_attempts",
300-
stats.evictionAttempts);
302+
std::accumulate(stats.evictionAttempts.begin(),stats.evictionAttempts.end(),0));
301303
counters_.updateDelta(statPrefix + "cache.alloc_failures",
302-
stats.allocFailures);
304+
std::accumulate(stats.allocFailures.begin(),stats.allocFailures.end(),0));
303305
counters_.updateDelta(statPrefix + "cache.invalid_allocs",
304306
stats.invalidAllocs);
305307

cachelib/allocator/CacheAllocator-inl.h

Lines changed: 124 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -408,9 +408,8 @@ CacheAllocator<CacheTrait>::allocateInternalTier(TierId tid,
408408
util::RollingLatencyTracker rollTracker{
409409
(*stats_.classAllocLatency)[tid][pid][cid]};
410410

411-
// TODO: per-tier
412-
(*stats_.allocAttempts)[pid][cid].inc();
413-
411+
(*stats_.allocAttempts)[tid][pid][cid].inc();
412+
414413
void* memory = allocator_[tid]->allocate(pid, requiredSize);
415414

416415
if (backgroundEvictor_.size() && !fromBgThread &&
@@ -438,12 +437,12 @@ CacheAllocator<CacheTrait>::allocateInternalTier(TierId tid,
438437
handle = acquire(new (memory) Item(key, size, creationTime, expiryTime));
439438
if (handle) {
440439
handle.markNascent();
441-
(*stats_.fragmentationSize)[pid][cid].add(
440+
(*stats_.fragmentationSize)[tid][pid][cid].add(
442441
util::getFragmentation(*this, *handle));
443442
}
444443

445444
} else { // failed to allocate memory.
446-
(*stats_.allocFailures)[pid][cid].inc(); // TODO: per-tier
445+
(*stats_.allocFailures)[tid][pid][cid].inc();
447446
// wake up rebalancer
448447
if (!config_.poolRebalancerDisableForcedWakeUp && poolRebalancer_) {
449448
poolRebalancer_->wakeUp();
@@ -515,16 +514,14 @@ CacheAllocator<CacheTrait>::allocateChainedItemInternal(const Item& parent,
515514
util::RollingLatencyTracker rollTracker{
516515
(*stats_.classAllocLatency)[tid][pid][cid]};
517516

518-
// TODO: per-tier? Right now stats_ are not used in any public periodic
519-
// worker
520-
(*stats_.allocAttempts)[pid][cid].inc();
517+
(*stats_.allocAttempts)[tid][pid][cid].inc();
521518

522519
void* memory = allocator_[tid]->allocate(pid, requiredSize);
523520
if (memory == nullptr) {
524521
memory = findEviction(tid, pid, cid);
525522
}
526523
if (memory == nullptr) {
527-
(*stats_.allocFailures)[pid][cid].inc();
524+
(*stats_.allocFailures)[tid][pid][cid].inc();
528525
return WriteHandle{};
529526
}
530527

@@ -535,7 +532,7 @@ CacheAllocator<CacheTrait>::allocateChainedItemInternal(const Item& parent,
535532

536533
if (child) {
537534
child.markNascent();
538-
(*stats_.fragmentationSize)[pid][cid].add(
535+
(*stats_.fragmentationSize)[tid][pid][cid].add(
539536
util::getFragmentation(*this, *child));
540537
}
541538

@@ -874,7 +871,7 @@ CacheAllocator<CacheTrait>::releaseBackToAllocator(Item& it,
874871
stats_.perPoolEvictionAgeSecs_[allocInfo.poolId].trackValue(refreshTime);
875872
}
876873

877-
(*stats_.fragmentationSize)[allocInfo.poolId][allocInfo.classId].sub(
874+
(*stats_.fragmentationSize)[tid][allocInfo.poolId][allocInfo.classId].sub(
878875
util::getFragmentation(*this, it));
879876

880877
// Chained items can only end up in this place if the user has allocated
@@ -957,7 +954,7 @@ CacheAllocator<CacheTrait>::releaseBackToAllocator(Item& it,
957954

958955
const auto childInfo =
959956
allocator_[tid]->getAllocInfo(static_cast<const void*>(head));
960-
(*stats_.fragmentationSize)[childInfo.poolId][childInfo.classId].sub(
957+
(*stats_.fragmentationSize)[tid][childInfo.poolId][childInfo.classId].sub(
961958
util::getFragmentation(*this, *head));
962959

963960
removeFromMMContainer(*head);
@@ -1403,20 +1400,20 @@ CacheAllocator<CacheTrait>::getNextCandidate(TierId tid,
14031400
auto& mmContainer = getMMContainer(tid, pid, cid);
14041401
bool lastTier = tid+1 >= getNumTiers();
14051402

1406-
mmContainer.withEvictionIterator([this, pid, cid, &candidate, &toRecycle,
1403+
mmContainer.withEvictionIterator([this, tid, pid, cid, &candidate, &toRecycle,
14071404
&searchTries, &mmContainer, &lastTier,
14081405
&token](auto&& itr) {
14091406
if (!itr) {
14101407
++searchTries;
1411-
(*stats_.evictionAttempts)[pid][cid].inc();
1408+
(*stats_.evictionAttempts)[tid][pid][cid].inc();
14121409
return;
14131410
}
14141411

14151412
while ((config_.evictionSearchTries == 0 ||
14161413
config_.evictionSearchTries > searchTries) &&
14171414
itr) {
14181415
++searchTries;
1419-
(*stats_.evictionAttempts)[pid][cid].inc();
1416+
(*stats_.evictionAttempts)[tid][pid][cid].inc();
14201417

14211418
auto* toRecycle_ = itr.get();
14221419
auto* candidate_ =
@@ -1522,6 +1519,7 @@ CacheAllocator<CacheTrait>::getNextCandidate(TierId tid,
15221519
XDCHECK(!candidate->isAccessible());
15231520
XDCHECK(candidate->getKey() == evictedToNext->getKey());
15241521

1522+
(*stats_.numWritebacks)[tid][pid][cid].inc();
15251523
wakeUpWaiters(candidate->getKey(), std::move(evictedToNext));
15261524
}
15271525

@@ -1549,9 +1547,9 @@ CacheAllocator<CacheTrait>::findEviction(TierId tid, PoolId pid, ClassId cid) {
15491547
// NULL. If `ref` == 0 then it means that we are the last holder of
15501548
// that item.
15511549
if (candidate->hasChainedItem()) {
1552-
(*stats_.chainedItemEvictions)[pid][cid].inc();
1550+
(*stats_.chainedItemEvictions)[tid][pid][cid].inc();
15531551
} else {
1554-
(*stats_.regularItemEvictions)[pid][cid].inc();
1552+
(*stats_.regularItemEvictions)[tid][pid][cid].inc();
15551553
}
15561554

15571555
if (auto eventTracker = getEventTracker()) {
@@ -2150,7 +2148,7 @@ bool CacheAllocator<CacheTrait>::recordAccessInMMContainer(Item& item,
21502148
const auto tid = getTierId(item);
21512149
const auto allocInfo =
21522150
allocator_[tid]->getAllocInfo(static_cast<const void*>(&item));
2153-
(*stats_.cacheHits)[allocInfo.poolId][allocInfo.classId].inc();
2151+
(*stats_.cacheHits)[tid][allocInfo.poolId][allocInfo.classId].inc();
21542152

21552153
// track recently accessed items if needed
21562154
if (UNLIKELY(config_.trackRecentItemsForDump)) {
@@ -2625,6 +2623,8 @@ size_t CacheAllocator<CacheTrait>::getPoolSize(PoolId poolId) const {
26252623

26262624
template <typename CacheTrait>
26272625
PoolStats CacheAllocator<CacheTrait>::getPoolStats(PoolId poolId) const {
2626+
//this pool ref is just used to get class ids, which will be the
2627+
//same across tiers
26282628
const auto& pool = allocator_[currentTier()]->getPool(poolId);
26292629
const auto& allocSizes = pool.getAllocSizes();
26302630
auto mpStats = pool.getStats();
@@ -2643,24 +2643,42 @@ PoolStats CacheAllocator<CacheTrait>::getPoolStats(PoolId poolId) const {
26432643
// TODO export evictions, numItems etc from compact cache directly.
26442644
if (!isCompactCache) {
26452645
for (const ClassId cid : classIds) {
2646-
uint64_t classHits = (*stats_.cacheHits)[poolId][cid].get();
2647-
XDCHECK(mmContainers_[currentTier()][poolId][cid],
2648-
folly::sformat("Pid {}, Cid {} not initialized.", poolId, cid));
2646+
uint64_t allocAttempts = 0, evictionAttempts = 0, allocFailures = 0,
2647+
fragmentationSize = 0, classHits = 0, chainedItemEvictions = 0,
2648+
regularItemEvictions = 0, numWritebacks = 0;
2649+
MMContainerStat mmContainerStats;
2650+
for (TierId tid = 0; tid < getNumTiers(); tid++) {
2651+
allocAttempts += (*stats_.allocAttempts)[tid][poolId][cid].get();
2652+
evictionAttempts += (*stats_.evictionAttempts)[tid][poolId][cid].get();
2653+
allocFailures += (*stats_.allocFailures)[tid][poolId][cid].get();
2654+
fragmentationSize += (*stats_.fragmentationSize)[tid][poolId][cid].get();
2655+
classHits += (*stats_.cacheHits)[tid][poolId][cid].get();
2656+
chainedItemEvictions += (*stats_.chainedItemEvictions)[tid][poolId][cid].get();
2657+
regularItemEvictions += (*stats_.regularItemEvictions)[tid][poolId][cid].get();
2658+
numWritebacks += (*stats_.numWritebacks)[tid][poolId][cid].get();
2659+
mmContainerStats += getMMContainerStat(tid, poolId, cid);
2660+
XDCHECK(mmContainers_[tid][poolId][cid],
2661+
folly::sformat("Tid {}, Pid {}, Cid {} not initialized.", tid, poolId, cid));
2662+
}
26492663
cacheStats.insert(
26502664
{cid,
2651-
{allocSizes[cid], (*stats_.allocAttempts)[poolId][cid].get(),
2652-
(*stats_.evictionAttempts)[poolId][cid].get(),
2653-
(*stats_.allocFailures)[poolId][cid].get(),
2654-
(*stats_.fragmentationSize)[poolId][cid].get(), classHits,
2655-
(*stats_.chainedItemEvictions)[poolId][cid].get(),
2656-
(*stats_.regularItemEvictions)[poolId][cid].get(),
2657-
getMMContainerStat(currentTier(), poolId, cid)}});
2665+
{allocSizes[cid],
2666+
allocAttempts,
2667+
evictionAttempts,
2668+
allocFailures,
2669+
fragmentationSize,
2670+
classHits,
2671+
chainedItemEvictions,
2672+
regularItemEvictions,
2673+
numWritebacks,
2674+
mmContainerStats}});
26582675
totalHits += classHits;
26592676
}
26602677
}
26612678

26622679
PoolStats ret;
26632680
ret.isCompactCache = isCompactCache;
2681+
//pool name is also shared among tiers
26642682
ret.poolName = allocator_[currentTier()]->getPoolName(poolId);
26652683
ret.poolSize = pool.getPoolSize();
26662684
ret.poolUsableSize = pool.getPoolUsableSize();
@@ -2673,6 +2691,60 @@ PoolStats CacheAllocator<CacheTrait>::getPoolStats(PoolId poolId) const {
26732691
return ret;
26742692
}
26752693

2694+
template <typename CacheTrait>
2695+
PoolStats CacheAllocator<CacheTrait>::getPoolStats(TierId tid, PoolId poolId) const {
2696+
const auto& pool = allocator_[tid]->getPool(poolId);
2697+
const auto& allocSizes = pool.getAllocSizes();
2698+
auto mpStats = pool.getStats();
2699+
const auto& classIds = mpStats.classIds;
2700+
2701+
// check if this is a compact cache.
2702+
bool isCompactCache = false;
2703+
{
2704+
std::shared_lock lock(compactCachePoolsLock_);
2705+
isCompactCache = isCompactCachePool_[poolId];
2706+
}
2707+
2708+
//std::unordered_map<ClassId, CacheStat> cacheStats;
2709+
folly::F14FastMap<ClassId, CacheStat> cacheStats;
2710+
uint64_t totalHits = 0;
2711+
// cacheStats is only menaningful for pools that are not compact caches.
2712+
// TODO export evictions, numItems etc from compact cache directly.
2713+
if (!isCompactCache) {
2714+
for (const ClassId cid : classIds) {
2715+
uint64_t classHits = (*stats_.cacheHits)[tid][poolId][cid].get();
2716+
XDCHECK(mmContainers_[tid][poolId][cid],
2717+
folly::sformat("Tid {}, Pid {}, Cid {} not initialized.", tid, poolId, cid));
2718+
cacheStats.insert(
2719+
{cid,
2720+
{allocSizes[cid],
2721+
(*stats_.allocAttempts)[tid][poolId][cid].get(),
2722+
(*stats_.evictionAttempts)[tid][poolId][cid].get(),
2723+
(*stats_.allocFailures)[tid][poolId][cid].get(),
2724+
(*stats_.fragmentationSize)[tid][poolId][cid].get(),
2725+
classHits,
2726+
(*stats_.chainedItemEvictions)[tid][poolId][cid].get(),
2727+
(*stats_.regularItemEvictions)[tid][poolId][cid].get(),
2728+
(*stats_.numWritebacks)[tid][poolId][cid].get(),
2729+
getMMContainerStat(tid, poolId, cid)}});
2730+
totalHits += classHits;
2731+
}
2732+
}
2733+
2734+
PoolStats ret;
2735+
ret.isCompactCache = isCompactCache;
2736+
ret.poolName = allocator_[tid]->getPoolName(poolId);
2737+
ret.poolSize = pool.getPoolSize();
2738+
ret.poolUsableSize = pool.getPoolUsableSize();
2739+
ret.poolAdvisedSize = pool.getPoolAdvisedSize();
2740+
ret.cacheStats = std::move(cacheStats);
2741+
ret.mpStats = std::move(mpStats);
2742+
ret.numPoolGetHits = totalHits;
2743+
ret.evictionAgeSecs = stats_.perPoolEvictionAgeSecs_[poolId].estimate();
2744+
2745+
return ret;
2746+
}
2747+
26762748
template <typename CacheTrait>
26772749
ACStats CacheAllocator<CacheTrait>::getACStats(TierId tid,
26782750
PoolId poolId,
@@ -2918,7 +2990,7 @@ bool CacheAllocator<CacheTrait>::moveForSlabRelease(Item& oldItem) {
29182990
}
29192991
allocator_[tid]->free(&oldItem);
29202992

2921-
(*stats_.fragmentationSize)[allocInfo.poolId][allocInfo.classId].sub(
2993+
(*stats_.fragmentationSize)[tid][allocInfo.poolId][allocInfo.classId].sub(
29222994
util::getFragmentation(*this, oldItem));
29232995
stats_.numMoveSuccesses.inc();
29242996
return true;
@@ -2993,12 +3065,13 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(Item& item) {
29933065
nvmCache_->put(*evicted, std::move(token));
29943066
}
29953067

3068+
const auto tid = getTierId(*evicted);
29963069
const auto allocInfo =
2997-
allocator_[getTierId(item)]->getAllocInfo(static_cast<const void*>(&item));
3070+
allocator_[tid]->getAllocInfo(static_cast<const void*>(evicted));
29983071
if (evicted->hasChainedItem()) {
2999-
(*stats_.chainedItemEvictions)[allocInfo.poolId][allocInfo.classId].inc();
3072+
(*stats_.chainedItemEvictions)[tid][allocInfo.poolId][allocInfo.classId].inc();
30003073
} else {
3001-
(*stats_.regularItemEvictions)[allocInfo.poolId][allocInfo.classId].inc();
3074+
(*stats_.regularItemEvictions)[tid][allocInfo.poolId][allocInfo.classId].inc();
30023075
}
30033076

30043077
stats_.numEvictionSuccesses.inc();
@@ -3232,8 +3305,13 @@ folly::IOBufQueue CacheAllocator<CacheTrait>::saveStateToIOBuf() {
32323305
for (PoolId pid : pools) {
32333306
for (unsigned int cid = 0; cid < (*stats_.fragmentationSize)[pid].size();
32343307
++cid) {
3308+
uint64_t fragmentationSize = 0;
3309+
for (TierId tid = 0; tid < getNumTiers(); tid++) {
3310+
fragmentationSize += (*stats_.fragmentationSize)[tid][pid][cid].get();
3311+
}
32353312
metadata_.fragmentationSize()[pid][static_cast<ClassId>(cid)] =
3236-
(*stats_.fragmentationSize)[pid][cid].get();
3313+
fragmentationSize;
3314+
32373315
}
32383316
if (isCompactCachePool_[pid]) {
32393317
metadata_.compactCachePools()->push_back(pid);
@@ -3479,8 +3557,19 @@ void CacheAllocator<CacheTrait>::initStats() {
34793557
// deserialize the fragmentation size of each thread.
34803558
for (const auto& pid : *metadata_.fragmentationSize()) {
34813559
for (const auto& cid : pid.second) {
3482-
(*stats_.fragmentationSize)[pid.first][cid.first].set(
3483-
static_cast<uint64_t>(cid.second));
3560+
//in multi-tier we serialized as the sum - no way
3561+
//to get back so just divide the two for now
3562+
//TODO: proper multi-tier serialization
3563+
uint64_t total = static_cast<uint64_t>(cid.second);
3564+
uint64_t part = total / getNumTiers();
3565+
uint64_t sum = 0;
3566+
for (TierId tid = 1; tid < getNumTiers(); tid++) {
3567+
(*stats_.fragmentationSize)[tid][pid.first][cid.first].set(part);
3568+
sum += part;
3569+
}
3570+
uint64_t leftover = total - sum;
3571+
(*stats_.fragmentationSize)[0][pid.first][cid.first].set(leftover);
3572+
34843573
}
34853574
}
34863575

cachelib/allocator/CacheAllocator.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,6 +1253,8 @@ class CacheAllocator : public CacheBase {
12531253

12541254
// pool stats by pool id
12551255
PoolStats getPoolStats(PoolId pid) const override final;
1256+
// pool stats by tier id and pool id
1257+
PoolStats getPoolStats(TierId tid, PoolId pid) const;
12561258

12571259
// This can be expensive so it is not part of PoolStats
12581260
PoolEvictionAgeStats getPoolEvictionAgeStats(
@@ -2049,9 +2051,9 @@ class CacheAllocator : public CacheBase {
20492051
XDCHECK(!candidate->isMarkedForEviction() && !candidate->isMoving());
20502052

20512053
if (candidate->hasChainedItem()) {
2052-
(*stats_.chainedItemEvictions)[pid][cid].inc();
2054+
(*stats_.chainedItemEvictions)[tid][pid][cid].inc();
20532055
} else {
2054-
(*stats_.regularItemEvictions)[pid][cid].inc();
2056+
(*stats_.regularItemEvictions)[tid][pid][cid].inc();
20552057
}
20562058

20572059
// it's safe to recycle the item here as there are no more

0 commit comments

Comments
 (0)