@@ -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
26262624template <typename CacheTrait>
26272625PoolStats 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+
26762748template <typename CacheTrait>
26772749ACStats 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
0 commit comments