@@ -418,8 +418,7 @@ CacheAllocator<CacheTrait>::allocateInternalTier(TierId tid,
418
418
util::RollingLatencyTracker rollTracker{
419
419
(*stats_.classAllocLatency )[tid][pid][cid]};
420
420
421
- // TODO: per-tier
422
- (*stats_.allocAttempts )[pid][cid].inc ();
421
+ (*stats_.allocAttempts )[tid][pid][cid].inc ();
423
422
424
423
void * memory = allocator_[tid]->allocate (pid, requiredSize);
425
424
@@ -445,12 +444,12 @@ CacheAllocator<CacheTrait>::allocateInternalTier(TierId tid,
445
444
handle = acquire (new (memory) Item (key, size, creationTime, expiryTime));
446
445
if (handle) {
447
446
handle.markNascent ();
448
- (*stats_.fragmentationSize )[pid][cid].add (
447
+ (*stats_.fragmentationSize )[tid][ pid][cid].add (
449
448
util::getFragmentation (*this , *handle));
450
449
}
451
450
452
451
} else { // failed to allocate memory.
453
- (*stats_.allocFailures )[pid][cid].inc (); // TODO: per-tier
452
+ (*stats_.allocFailures )[tid][ pid][cid].inc ();
454
453
// wake up rebalancer
455
454
if (poolRebalancer_) {
456
455
poolRebalancer_->wakeUp ();
@@ -522,16 +521,14 @@ CacheAllocator<CacheTrait>::allocateChainedItemInternal(
522
521
util::RollingLatencyTracker rollTracker{
523
522
(*stats_.classAllocLatency )[tid][pid][cid]};
524
523
525
- // TODO: per-tier? Right now stats_ are not used in any public periodic
526
- // worker
527
- (*stats_.allocAttempts )[pid][cid].inc ();
524
+ (*stats_.allocAttempts )[tid][pid][cid].inc ();
528
525
529
526
void * memory = allocator_[tid]->allocate (pid, requiredSize);
530
527
if (memory == nullptr ) {
531
528
memory = findEviction (tid, pid, cid);
532
529
}
533
530
if (memory == nullptr ) {
534
- (*stats_.allocFailures )[pid][cid].inc ();
531
+ (*stats_.allocFailures )[tid][ pid][cid].inc ();
535
532
return WriteHandle{};
536
533
}
537
534
@@ -543,7 +540,7 @@ CacheAllocator<CacheTrait>::allocateChainedItemInternal(
543
540
544
541
if (child) {
545
542
child.markNascent ();
546
- (*stats_.fragmentationSize )[pid][cid].add (
543
+ (*stats_.fragmentationSize )[tid][ pid][cid].add (
547
544
util::getFragmentation (*this , *child));
548
545
}
549
546
@@ -858,7 +855,7 @@ CacheAllocator<CacheTrait>::releaseBackToAllocator(Item& it,
858
855
stats_.perPoolEvictionAgeSecs_ [allocInfo.poolId ].trackValue (refreshTime);
859
856
}
860
857
861
- (*stats_.fragmentationSize )[allocInfo.poolId ][allocInfo.classId ].sub (
858
+ (*stats_.fragmentationSize )[tid][ allocInfo.poolId ][allocInfo.classId ].sub (
862
859
util::getFragmentation (*this , it));
863
860
864
861
// Chained items can only end up in this place if the user has allocated
@@ -941,7 +938,7 @@ CacheAllocator<CacheTrait>::releaseBackToAllocator(Item& it,
941
938
942
939
const auto childInfo =
943
940
allocator_[tid]->getAllocInfo (static_cast <const void *>(head));
944
- (*stats_.fragmentationSize )[childInfo.poolId ][childInfo.classId ].sub (
941
+ (*stats_.fragmentationSize )[tid][ childInfo.poolId ][childInfo.classId ].sub (
945
942
util::getFragmentation (*this , *head));
946
943
947
944
removeFromMMContainer (*head);
@@ -1585,20 +1582,20 @@ CacheAllocator<CacheTrait>::findEviction(TierId tid, PoolId pid, ClassId cid) {
1585
1582
Item* candidate = nullptr ;
1586
1583
typename NvmCacheT::PutToken token;
1587
1584
1588
- mmContainer.withEvictionIterator ([this , pid, cid, &candidate, &toRecycle,
1585
+ mmContainer.withEvictionIterator ([this , tid, pid, cid, &candidate, &toRecycle,
1589
1586
&searchTries, &mmContainer, &lastTier,
1590
1587
&token](auto && itr) {
1591
1588
if (!itr) {
1592
1589
++searchTries;
1593
- (*stats_.evictionAttempts )[pid][cid].inc ();
1590
+ (*stats_.evictionAttempts )[tid][ pid][cid].inc ();
1594
1591
return ;
1595
1592
}
1596
1593
1597
1594
while ((config_.evictionSearchTries == 0 ||
1598
1595
config_.evictionSearchTries > searchTries) &&
1599
1596
itr) {
1600
1597
++searchTries;
1601
- (*stats_.evictionAttempts )[pid][cid].inc ();
1598
+ (*stats_.evictionAttempts )[tid][ pid][cid].inc ();
1602
1599
1603
1600
auto * toRecycle_ = itr.get ();
1604
1601
auto * candidate_ =
@@ -1698,6 +1695,7 @@ CacheAllocator<CacheTrait>::findEviction(TierId tid, PoolId pid, ClassId cid) {
1698
1695
XDCHECK (!candidate->isAccessible ());
1699
1696
XDCHECK (candidate->getKey () == evictedToNext->getKey ());
1700
1697
1698
+ (*stats_.numWritebacks )[tid][pid][cid].inc ();
1701
1699
wakeUpWaiters (*candidate, std::move (evictedToNext));
1702
1700
}
1703
1701
@@ -1707,9 +1705,9 @@ CacheAllocator<CacheTrait>::findEviction(TierId tid, PoolId pid, ClassId cid) {
1707
1705
// NULL. If `ref` == 0 then it means that we are the last holder of
1708
1706
// that item.
1709
1707
if (candidate->hasChainedItem ()) {
1710
- (*stats_.chainedItemEvictions )[pid][cid].inc ();
1708
+ (*stats_.chainedItemEvictions )[tid][ pid][cid].inc ();
1711
1709
} else {
1712
- (*stats_.regularItemEvictions )[pid][cid].inc ();
1710
+ (*stats_.regularItemEvictions )[tid][ pid][cid].inc ();
1713
1711
}
1714
1712
1715
1713
if (auto eventTracker = getEventTracker ()) {
@@ -2304,7 +2302,7 @@ bool CacheAllocator<CacheTrait>::recordAccessInMMContainer(Item& item,
2304
2302
const auto tid = getTierId (item);
2305
2303
const auto allocInfo =
2306
2304
allocator_[tid]->getAllocInfo (static_cast <const void *>(&item));
2307
- (*stats_.cacheHits )[allocInfo.poolId ][allocInfo.classId ].inc ();
2305
+ (*stats_.cacheHits )[tid][ allocInfo.poolId ][allocInfo.classId ].inc ();
2308
2306
2309
2307
// track recently accessed items if needed
2310
2308
if (UNLIKELY (config_.trackRecentItemsForDump )) {
@@ -2773,6 +2771,8 @@ size_t CacheAllocator<CacheTrait>::getPoolSize(PoolId poolId) const {
2773
2771
2774
2772
template <typename CacheTrait>
2775
2773
PoolStats CacheAllocator<CacheTrait>::getPoolStats(PoolId poolId) const {
2774
+ // this pool ref is just used to get class ids, which will be the
2775
+ // same across tiers
2776
2776
const auto & pool = allocator_[currentTier ()]->getPool (poolId);
2777
2777
const auto & allocSizes = pool.getAllocSizes ();
2778
2778
auto mpStats = pool.getStats ();
@@ -2791,24 +2791,42 @@ PoolStats CacheAllocator<CacheTrait>::getPoolStats(PoolId poolId) const {
2791
2791
// TODO export evictions, numItems etc from compact cache directly.
2792
2792
if (!isCompactCache) {
2793
2793
for (const ClassId cid : classIds) {
2794
- uint64_t classHits = (*stats_.cacheHits )[poolId][cid].get ();
2795
- XDCHECK (mmContainers_[currentTier ()][poolId][cid],
2796
- folly::sformat (" Pid {}, Cid {} not initialized." , poolId, cid));
2794
+ uint64_t allocAttempts, evictionAttempts, allocFailures,
2795
+ fragmentationSize, classHits, chainedItemEvictions,
2796
+ regularItemEvictions, numWritebacks = 0 ;
2797
+ MMContainerStat mmContainerStats;
2798
+ for (TierId tid = 0 ; tid < getNumTiers (); tid++) {
2799
+ allocAttempts += (*stats_.allocAttempts )[tid][poolId][cid].get ();
2800
+ evictionAttempts += (*stats_.evictionAttempts )[tid][poolId][cid].get ();
2801
+ allocFailures += (*stats_.allocFailures )[tid][poolId][cid].get ();
2802
+ fragmentationSize += (*stats_.fragmentationSize )[tid][poolId][cid].get ();
2803
+ classHits += (*stats_.cacheHits )[tid][poolId][cid].get ();
2804
+ chainedItemEvictions += (*stats_.chainedItemEvictions )[tid][poolId][cid].get ();
2805
+ regularItemEvictions += (*stats_.regularItemEvictions )[tid][poolId][cid].get ();
2806
+ numWritebacks += (*stats_.numWritebacks )[tid][poolId][cid].get ();
2807
+ mmContainerStats += getMMContainerStat (tid, poolId, cid);
2808
+ XDCHECK (mmContainers_[tid][poolId][cid],
2809
+ folly::sformat (" Tid {}, Pid {}, Cid {} not initialized." , tid, poolId, cid));
2810
+ }
2797
2811
cacheStats.insert (
2798
2812
{cid,
2799
- {allocSizes[cid], (*stats_.allocAttempts )[poolId][cid].get (),
2800
- (*stats_.evictionAttempts )[poolId][cid].get (),
2801
- (*stats_.allocFailures )[poolId][cid].get (),
2802
- (*stats_.fragmentationSize )[poolId][cid].get (), classHits,
2803
- (*stats_.chainedItemEvictions )[poolId][cid].get (),
2804
- (*stats_.regularItemEvictions )[poolId][cid].get (),
2805
- getMMContainerStat (currentTier (), poolId, cid)}});
2813
+ {allocSizes[cid],
2814
+ allocAttempts,
2815
+ evictionAttempts,
2816
+ allocFailures,
2817
+ fragmentationSize,
2818
+ classHits,
2819
+ chainedItemEvictions,
2820
+ regularItemEvictions,
2821
+ numWritebacks,
2822
+ mmContainerStats}});
2806
2823
totalHits += classHits;
2807
2824
}
2808
2825
}
2809
2826
2810
2827
PoolStats ret;
2811
2828
ret.isCompactCache = isCompactCache;
2829
+ // pool name is also shared among tiers
2812
2830
ret.poolName = allocator_[currentTier ()]->getPoolName (poolId);
2813
2831
ret.poolSize = pool.getPoolSize ();
2814
2832
ret.poolUsableSize = pool.getPoolUsableSize ();
@@ -2821,6 +2839,59 @@ PoolStats CacheAllocator<CacheTrait>::getPoolStats(PoolId poolId) const {
2821
2839
return ret;
2822
2840
}
2823
2841
2842
+ template <typename CacheTrait>
2843
+ PoolStats CacheAllocator<CacheTrait>::getPoolStats(TierId tid, PoolId poolId) const {
2844
+ const auto & pool = allocator_[tid]->getPool (poolId);
2845
+ const auto & allocSizes = pool.getAllocSizes ();
2846
+ auto mpStats = pool.getStats ();
2847
+ const auto & classIds = mpStats.classIds ;
2848
+
2849
+ // check if this is a compact cache.
2850
+ bool isCompactCache = false ;
2851
+ {
2852
+ folly::SharedMutex::ReadHolder lock (compactCachePoolsLock_);
2853
+ isCompactCache = isCompactCachePool_[poolId];
2854
+ }
2855
+
2856
+ std::unordered_map<ClassId, CacheStat> cacheStats;
2857
+ uint64_t totalHits = 0 ;
2858
+ // cacheStats is only menaningful for pools that are not compact caches.
2859
+ // TODO export evictions, numItems etc from compact cache directly.
2860
+ if (!isCompactCache) {
2861
+ for (const ClassId cid : classIds) {
2862
+ uint64_t classHits = (*stats_.cacheHits )[tid][poolId][cid].get ();
2863
+ XDCHECK (mmContainers_[tid][poolId][cid],
2864
+ folly::sformat (" Tid {}, Pid {}, Cid {} not initialized." , tid, poolId, cid));
2865
+ cacheStats.insert (
2866
+ {cid,
2867
+ {allocSizes[cid],
2868
+ (*stats_.allocAttempts )[tid][poolId][cid].get (),
2869
+ (*stats_.evictionAttempts )[tid][poolId][cid].get (),
2870
+ (*stats_.allocFailures )[tid][poolId][cid].get (),
2871
+ (*stats_.fragmentationSize )[tid][poolId][cid].get (),
2872
+ classHits,
2873
+ (*stats_.chainedItemEvictions )[tid][poolId][cid].get (),
2874
+ (*stats_.regularItemEvictions )[tid][poolId][cid].get (),
2875
+ (*stats_.numWritebacks )[tid][poolId][cid].get (),
2876
+ getMMContainerStat (tid, poolId, cid)}});
2877
+ totalHits += classHits;
2878
+ }
2879
+ }
2880
+
2881
+ PoolStats ret;
2882
+ ret.isCompactCache = isCompactCache;
2883
+ ret.poolName = allocator_[tid]->getPoolName (poolId);
2884
+ ret.poolSize = pool.getPoolSize ();
2885
+ ret.poolUsableSize = pool.getPoolUsableSize ();
2886
+ ret.poolAdvisedSize = pool.getPoolAdvisedSize ();
2887
+ ret.cacheStats = std::move (cacheStats);
2888
+ ret.mpStats = std::move (mpStats);
2889
+ ret.numPoolGetHits = totalHits;
2890
+ ret.evictionAgeSecs = stats_.perPoolEvictionAgeSecs_ [poolId].estimate ();
2891
+
2892
+ return ret;
2893
+ }
2894
+
2824
2895
template <typename CacheTrait>
2825
2896
ACStats CacheAllocator<CacheTrait>::getACStats(TierId tid,
2826
2897
PoolId poolId,
@@ -3072,7 +3143,7 @@ bool CacheAllocator<CacheTrait>::moveForSlabRelease(
3072
3143
const auto allocInfo = allocator_[tid]->getAllocInfo (oldItem.getMemory ());
3073
3144
allocator_[tid]->free (&oldItem);
3074
3145
3075
- (*stats_.fragmentationSize )[allocInfo.poolId ][allocInfo.classId ].sub (
3146
+ (*stats_.fragmentationSize )[tid][ allocInfo.poolId ][allocInfo.classId ].sub (
3076
3147
util::getFragmentation (*this , oldItem));
3077
3148
stats_.numMoveSuccesses .inc ();
3078
3149
return true ;
@@ -3351,12 +3422,13 @@ void CacheAllocator<CacheTrait>::evictForSlabRelease(
3351
3422
nvmCache_->put (*evicted, std::move (token));
3352
3423
}
3353
3424
3425
+ const auto tid = getTierId (*evicted);
3354
3426
const auto allocInfo =
3355
- allocator_[getTierId (*evicted) ]->getAllocInfo (static_cast <const void *>(evicted));
3427
+ allocator_[tid ]->getAllocInfo (static_cast <const void *>(evicted));
3356
3428
if (evicted->hasChainedItem ()) {
3357
- (*stats_.chainedItemEvictions )[allocInfo.poolId ][allocInfo.classId ].inc ();
3429
+ (*stats_.chainedItemEvictions )[tid][ allocInfo.poolId ][allocInfo.classId ].inc ();
3358
3430
} else {
3359
- (*stats_.regularItemEvictions )[allocInfo.poolId ][allocInfo.classId ].inc ();
3431
+ (*stats_.regularItemEvictions )[tid][ allocInfo.poolId ][allocInfo.classId ].inc ();
3360
3432
}
3361
3433
3362
3434
stats_.numEvictionSuccesses .inc ();
@@ -3579,8 +3651,13 @@ folly::IOBufQueue CacheAllocator<CacheTrait>::saveStateToIOBuf() {
3579
3651
for (PoolId pid : pools) {
3580
3652
for (unsigned int cid = 0 ; cid < (*stats_.fragmentationSize )[pid].size ();
3581
3653
++cid) {
3654
+ uint64_t fragmentationSize = 0 ;
3655
+ for (TierId tid = 0 ; tid < getNumTiers (); tid++) {
3656
+ fragmentationSize += (*stats_.fragmentationSize )[tid][pid][cid].get ();
3657
+ }
3582
3658
metadata_.fragmentationSize ()[pid][static_cast <ClassId>(cid)] =
3583
- (*stats_.fragmentationSize )[pid][cid].get ();
3659
+ fragmentationSize;
3660
+
3584
3661
}
3585
3662
if (isCompactCachePool_[pid]) {
3586
3663
metadata_.compactCachePools ()->push_back (pid);
@@ -3826,8 +3903,19 @@ void CacheAllocator<CacheTrait>::initStats() {
3826
3903
// deserialize the fragmentation size of each thread.
3827
3904
for (const auto & pid : *metadata_.fragmentationSize ()) {
3828
3905
for (const auto & cid : pid.second ) {
3829
- (*stats_.fragmentationSize )[pid.first ][cid.first ].set (
3830
- static_cast <uint64_t >(cid.second ));
3906
+ // in multi-tier we serialized as the sum - no way
3907
+ // to get back so just divide the two for now
3908
+ // TODO: proper multi-tier serialization
3909
+ uint64_t total = static_cast <uint64_t >(cid.second );
3910
+ uint64_t part = total / getNumTiers ();
3911
+ uint64_t sum = 0 ;
3912
+ for (TierId tid = 1 ; tid < getNumTiers (); tid++) {
3913
+ (*stats_.fragmentationSize )[tid][pid.first ][cid.first ].set (part);
3914
+ sum += part;
3915
+ }
3916
+ uint64_t leftover = total - sum;
3917
+ (*stats_.fragmentationSize )[0 ][pid.first ][cid.first ].set (leftover);
3918
+
3831
3919
}
3832
3920
}
3833
3921
0 commit comments