diff --git a/cachelib/allocator/BackgroundMover-inl.h b/cachelib/allocator/BackgroundMover-inl.h index 2b1c55c94e..d65e732202 100644 --- a/cachelib/allocator/BackgroundMover-inl.h +++ b/cachelib/allocator/BackgroundMover-inl.h @@ -98,6 +98,7 @@ BackgroundMoverStats BackgroundMover::getStats() const noexcept { stats.runCount = numTraversals.get(); stats.totalBytesMoved = totalBytesMoved.get(); stats.totalClasses = totalClasses.get(); + stats.strategyStats = strategy_->getStats(); return stats; } diff --git a/cachelib/allocator/BackgroundMoverStrategy.h b/cachelib/allocator/BackgroundMoverStrategy.h index 08000c306c..1d586277ab 100644 --- a/cachelib/allocator/BackgroundMoverStrategy.h +++ b/cachelib/allocator/BackgroundMoverStrategy.h @@ -27,6 +27,7 @@ class BackgroundMoverStrategy { virtual std::vector calculateBatchSizes( const CacheBase& cache, std::vector> acVec) = 0; + virtual BackgroundStrategyStats getStats() = 0; }; } // namespace cachelib diff --git a/cachelib/allocator/CacheAllocator.h b/cachelib/allocator/CacheAllocator.h index 802abb0115..aef7a43c3a 100644 --- a/cachelib/allocator/CacheAllocator.h +++ b/cachelib/allocator/CacheAllocator.h @@ -1130,7 +1130,14 @@ class CacheAllocator : public CacheBase { return stats; } - + + /* BackgroundPromotionStats getBackgroundPromoterStats() const { + auto stats = BackgroundPromotionStats{}; + for (auto &bg : backgroundPromoter_) + stats += bg->getStats(); + return stats; + } + */ std::map>> getBackgroundMoverClassStats(MoverDir direction) const { diff --git a/cachelib/allocator/CacheStats.h b/cachelib/allocator/CacheStats.h index df718ab8c3..2913fa5c60 100644 --- a/cachelib/allocator/CacheStats.h +++ b/cachelib/allocator/CacheStats.h @@ -303,6 +303,28 @@ struct ReaperStats { // indicates the average of all traversals uint64_t avgTraversalTimeMs{0}; }; +struct BackgroundStrategyStats { + + std::map > highEvictionAcWatermarks; + std::map > acLatencies; + + + BackgroundStrategyStats& operator+=(const BackgroundStrategyStats& rhs){ + for (const auto entry : rhs.highEvictionAcWatermarks) { + auto cid = entry.first; + auto count = entry.second; + highEvictionAcWatermarks[cid] = count; + } + + for (const auto entry : rhs.acLatencies) { + auto cid = entry.first; + auto count = entry.second; + acLatencies[cid] = count; + } + return *this; + } + +}; // Mover Stats struct BackgroundMoverStats { @@ -315,15 +337,31 @@ struct BackgroundMoverStats { // eviction size uint64_t totalBytesMoved{0}; + BackgroundStrategyStats strategyStats; + BackgroundStrategyStats s; BackgroundMoverStats& operator+=(const BackgroundMoverStats& rhs) { numMovedItems += rhs.numMovedItems; runCount += rhs.runCount; totalClasses += rhs.totalClasses; totalBytesMoved += rhs.totalBytesMoved; + strategyStats += rhs.strategyStats; return *this; } }; +struct BackgroundPromotionStats { + // the number of items this worker evicted by looking at pools/classes stats + uint64_t numPromotedItems{0}; + + // number of times we went executed the thread //TODO: is this def correct? + uint64_t runCount{0}; + + BackgroundPromotionStats& operator+=(const BackgroundPromotionStats& rhs) { + numPromotedItems += rhs.numPromotedItems; + runCount += rhs.runCount; + return *this; + } +}; // CacheMetadata type to export struct CacheMetadata { diff --git a/cachelib/allocator/FreeThresholdStrategy.cpp b/cachelib/allocator/FreeThresholdStrategy.cpp index d4b8bad758..d4387b2888 100644 --- a/cachelib/allocator/FreeThresholdStrategy.cpp +++ b/cachelib/allocator/FreeThresholdStrategy.cpp @@ -16,6 +16,11 @@ #include "cachelib/allocator/FreeThresholdStrategy.h" +#include "cachelib/allocator/memory/MemoryPoolManager.h" +#include "cachelib/allocator/memory/MemoryAllocator.h" +#include "cachelib/allocator/Cache.h" +#include "cachelib/allocator/CacheStats.h" + #include namespace facebook { @@ -28,7 +33,15 @@ FreeThresholdStrategy::FreeThresholdStrategy(double lowEvictionAcWatermark, : lowEvictionAcWatermark(lowEvictionAcWatermark), highEvictionAcWatermark(highEvictionAcWatermark), maxEvictionBatch(maxEvictionBatch), - minEvictionBatch(minEvictionBatch) {} + minEvictionBatch(minEvictionBatch), + highEvictionAcWatermarks(CacheBase::kMaxTiers, + std::vector>>(MemoryPoolManager::kMaxPools, + std::vector>(MemoryAllocator::kMaxClasses, + std::vector(3, highEvictionAcWatermark)))), + acLatencies(CacheBase::kMaxTiers, + std::vector>>(MemoryPoolManager::kMaxPools, + std::vector>(MemoryAllocator::kMaxClasses, + std::vector(2, 0.0)))) {} std::vector FreeThresholdStrategy::calculateBatchSizes( const CacheBase& cache, @@ -43,6 +56,9 @@ std::vector FreeThresholdStrategy::calculateBatchSizes( auto toFreeItems = static_cast( toFreeMemPercent * stats.memorySize / stats.allocSize); batches.push_back(toFreeItems); + auto acAllocLatencyNs = cache.getAllocationClassStats(tid, pid, cid).allocLatencyNs.estimate(); //moving avg latency estimation for ac class + calculateLatency(acAllocLatencyNs, tid, pid, cid); + } } @@ -70,5 +86,41 @@ std::vector FreeThresholdStrategy::calculateBatchSizes( return batches; } +void FreeThresholdStrategy::calculateLatency(uint64_t acLatency, unsigned int tid, PoolId pid, ClassId cid){ + + auto best_latency= acLatencies[tid][pid][cid][0]; + acLatencies[tid][pid][cid][1]=best_latency; + acLatencies[tid][pid][cid][0]=acLatency; + + + +} + +BackgroundStrategyStats FreeThresholdStrategy::getStats() { + BackgroundStrategyStats s; + + + + auto numClasses = MemoryAllocator::kMaxClasses; + for (int i = 0; i < 1; i++) { + for (int j = 0; j < 1; j++) { + for (int k = 0; k < numClasses; k++) { + s.highEvictionAcWatermarks[k] = + std::make_tuple ( + highEvictionAcWatermarks[i][j][k][0], + highEvictionAcWatermarks[i][j][k][1], + highEvictionAcWatermarks[i][j][k][2]); + s.acLatencies[k]= + std::make_pair ( + acLatencies[i][j][k][0], + acLatencies[i][j][k][1] ); + + } + } + } + return s; +} + + } // namespace cachelib } // namespace facebook diff --git a/cachelib/allocator/FreeThresholdStrategy.h b/cachelib/allocator/FreeThresholdStrategy.h index 7103771852..d4b205f518 100644 --- a/cachelib/allocator/FreeThresholdStrategy.h +++ b/cachelib/allocator/FreeThresholdStrategy.h @@ -34,12 +34,21 @@ class FreeThresholdStrategy : public BackgroundMoverStrategy { std::vector calculateBatchSizes( const CacheBase& cache, std::vector> acVecs); + BackgroundStrategyStats getStats(); private: double lowEvictionAcWatermark{2.0}; double highEvictionAcWatermark{5.0}; uint64_t maxEvictionBatch{40}; uint64_t minEvictionBatch{5}; + std::vector>>> highEvictionAcWatermarks; + + std::vector>>> acLatencies; + +private: + //void calculateBenefitMig(uint64_t p99, unsigned int tid, PoolId pid, ClassId cid); //function to calculate the benefit of eviction for a certain ac class + void calculateLatency(uint64_t p99, unsigned int tid, PoolId pid, ClassId cid); + }; } // namespace cachelib diff --git a/cachelib/allocator/PromotionStrategy.h b/cachelib/allocator/PromotionStrategy.h index d5b491bea2..458ecc64e4 100644 --- a/cachelib/allocator/PromotionStrategy.h +++ b/cachelib/allocator/PromotionStrategy.h @@ -73,6 +73,10 @@ class PromotionStrategy : public BackgroundMoverStrategy { return batches; } + BackgroundStrategyStats getStats() { + BackgroundStrategyStats s; + return s; + } private: double promotionAcWatermark{4.0}; diff --git a/cachelib/cachebench/cache/Cache-inl.h b/cachelib/cachebench/cache/Cache-inl.h index a236fe0f75..b52856a9d5 100644 --- a/cachelib/cachebench/cache/Cache-inl.h +++ b/cachelib/cachebench/cache/Cache-inl.h @@ -14,6 +14,21 @@ * limitations under the License. */ +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "cachelib/allocator/Util.h" +#include "cachelib/allocator/nvmcache/NavyConfig.h" +#include "cachelib/cachebench/cache/ItemRecords.h" +#include "cachelib/cachebench/util/NandWrites.h" + namespace facebook { namespace cachelib { namespace cachebench { @@ -641,6 +656,10 @@ Stats Cache::getStats() const { cacheStats.promotionStats.numMovedItems; ret.backgndPromoStats.nTraversals = cacheStats.promotionStats.runCount; + ret.backgndEvicStats.nClasses = + cacheStats.promotionStats.totalClasses; + ret.backgndEvicStats.evictionSize = + cacheStats.promotionStats.totalBytesMoved; ret.numEvictions = aggregate.numEvictions(); ret.numItems = aggregate.numItems(); @@ -694,6 +713,8 @@ Stats Cache::getStats() const { ret.nvmCounters = cache_->getNvmCacheStatsMap(); } + ret.acHighWatermarks = cacheStats.evictionStats.strategyStats.highEvictionAcWatermarks; + ret.acLatencies = cacheStats.evictionStats.strategyStats.acLatencies; ret.backgroundEvictionClasses = cache_->getBackgroundMoverClassStats(MoverDir::Evict); ret.backgroundPromotionClasses = cache_->getBackgroundMoverClassStats(MoverDir::Promote); diff --git a/cachelib/cachebench/cache/CacheStats.h b/cachelib/cachebench/cache/CacheStats.h index 7568cae954..af13ed9556 100644 --- a/cachelib/cachebench/cache/CacheStats.h +++ b/cachelib/cachebench/cache/CacheStats.h @@ -139,6 +139,9 @@ struct Stats { std::map>> backgroundEvictionClasses; std::map>> backgroundPromotionClasses; + std::map> acHighWatermarks; + std::map> acLatencies; + // errors from the nvm engine. std::unordered_map nvmErrors; @@ -274,6 +277,8 @@ struct Stats { tid, pid, cid, promoted) << std::endl; }); } + + if (numNvmGets > 0 || numNvmDeletes > 0 || numNvmPuts > 0) { const double ramHitRatio = invertPctFn(numCacheGetMiss, numCacheGets); @@ -403,6 +408,23 @@ struct Stats { } } + /*if (!acHighWatermarks.empty() && backgndEvicStats.nEvictedItems > 0 ) { + out << "== Class High Threshold ==" << std::endl; + for (const auto& it : acHighWatermarks) { + //const& t = it.second + out << it.first << " : " << std::get<0>(it.second) <<" : " << std::get<1>(it.second) << " : " <(it.second) << std::endl; + } + } + */ + if (!acLatencies.empty() && backgndEvicStats.nEvictedItems > 0 ) { + out << "== Class Latencies ==" << std::endl; + for (const auto& it : acLatencies) { + out << it.first << " : " << it.second.first << " : " << it.second.second << std::endl; + } + } + + + if (numRamDestructorCalls > 0 || numNvmDestructorCalls > 0) { out << folly::sformat("Destructor executed from RAM {}, from NVM {}", numRamDestructorCalls, numNvmDestructorCalls) diff --git a/cachelib/cachebench/test_configs/hit_ratio/graph_cache_leader_fbobj/config-4GB-DRAM-4GB-PMEM-default_new_test4.json b/cachelib/cachebench/test_configs/hit_ratio/graph_cache_leader_fbobj/config-4GB-DRAM-4GB-PMEM-default_new_test4.json new file mode 100644 index 0000000000..7a2cd80bea --- /dev/null +++ b/cachelib/cachebench/test_configs/hit_ratio/graph_cache_leader_fbobj/config-4GB-DRAM-4GB-PMEM-default_new_test4.json @@ -0,0 +1,59 @@ +{ + "cache_config": + { + "cacheSizeMB": 8192, + "usePosixShm": true, + "poolRebalanceIntervalSec": 0, + "persistedCacheDir": "/tmp/mem-tier", + "htBucketPower" : 28, + "htLockPower" : 28, + "moveOnSlabRelease": false, + "memoryTiers" : [ + { + "ratio": 1 + }, + { + "ratio": 1, + "file":"/mnt/tmpfs_pmem/tier" + } + ], + "backgroundEvictorIntervalMilSec" : 10, + "evictorThreads" : 4, + "evictionHotnessThreshold" : 200, + "evictionSlabWatermark" : 100, + "lowEvictionAcWatermark" : 98.0, + "highEvictionAcWatermark" : 95.0, + "backgroundPromoterIntervalMilSec" : 10, + "promoterThreads" : 4, + "evictionHotnessThreshold" : 200, + "numDuplicateElements" : 0, + "promotionAcWatermark" : 97 + }, + "test_config": + { + "validateValue": true, + "opDelayNs": 1000000, + "opDelayBatch": 3, + "generator": "workload", + "addChainedRatio": 0.0, + "delRatio": 0.0, + "enableLookaside": true, + "numKeys": 71605574, + "numOps": 1250000, + "numThreads": 24, + "getRatio": 0.9568797693103636, + "loneGetRatio": 0.043120230689636455, + "keySizeRange": [ + 1, + 8, + 64 + ], + "keySizeRangeProbability": [ + 0.3, + 0.7 + ], + "popDistFile": "pop.json", + "setRatio": 0.0, + "valSizeDistFile": "sizes.json" + } +}