diff --git a/cachelib/allocator/CacheAllocator-inl.h b/cachelib/allocator/CacheAllocator-inl.h index 81eae340cf..6b4eb37cd4 100644 --- a/cachelib/allocator/CacheAllocator-inl.h +++ b/cachelib/allocator/CacheAllocator-inl.h @@ -416,6 +416,21 @@ CacheAllocator::allocateInternalTier(TierId tid, return handle; } +template +typename CacheAllocator::TierId +CacheAllocator::getTargetTierForItem(PoolId pid, + typename Item::Key key, + uint32_t size, + uint32_t creationTime, + uint32_t expiryTime) { + // TODO, also look at size and other things (depending on policy?) + // if (memUsage > highAllocationWatermark) return 1; + // else if (memUsage < highAllocationWatermark) return 0; + // else return random() % 2; + + return 0; +} + template typename CacheAllocator::WriteHandle CacheAllocator::allocateInternal(PoolId pid, @@ -423,8 +438,8 @@ CacheAllocator::allocateInternal(PoolId pid, uint32_t size, uint32_t creationTime, uint32_t expiryTime) { - auto tid = 0; /* TODO: consult admission policy */ - for(TierId tid = 0; tid < numTiers_; ++tid) { + auto tid = getTargetTierForItem(pid, key, size, creationTime, expiryTime); + for(; tid < numTiers_; ++tid) { auto handle = allocateInternalTier(tid, pid, key, size, creationTime, expiryTime); if (handle) return handle; } @@ -1849,7 +1864,13 @@ bool CacheAllocator::recordAccessInMMContainer(Item& item, } auto& mmContainer = getMMContainer(tid, allocInfo.poolId, allocInfo.classId); - return mmContainer.recordAccess(item, mode); + + // TODO: it would be better to have this hidden inside recordAccess perhaps + // Ideally, we can have different MMContainers for different tiers + if (tid == 0 || folly::rand32() % 128 < config_.markUsefulChance) + return mmContainer.recordAccess(item, mode); + + return true; } template diff --git a/cachelib/allocator/CacheAllocator.h b/cachelib/allocator/CacheAllocator.h index 24d0b89cb2..9845bb27e2 100644 --- a/cachelib/allocator/CacheAllocator.h +++ b/cachelib/allocator/CacheAllocator.h @@ -1987,6 +1987,8 @@ class CacheAllocator : public CacheBase { // indicates if the shutdown of cache is in progress or not std::atomic shutDownInProgress_{false}; + std::ACStats + // END private members // Make this friend to give access to acquire and release diff --git a/cachelib/allocator/CacheAllocatorConfig.h b/cachelib/allocator/CacheAllocatorConfig.h index 1d11b3ef14..790fd1a909 100644 --- a/cachelib/allocator/CacheAllocatorConfig.h +++ b/cachelib/allocator/CacheAllocatorConfig.h @@ -578,6 +578,21 @@ class CacheAllocatorConfig { // skip promote children items in chained when parent fail to promote bool skipPromoteChildrenWhenParentFailed{false}; + std::string admissionPolicy{"random"}; // where to put allocated item, used when free mem between lowAllocationWatermark and highAllocationWatermark + std::string evictionPolicy{""}; // where to put evicted item (where in MMContainer?) + std::string promotionPolicy{""}; // which item to promote + uint64_t markUsefulChance{128}; // how to mark items as useful on lower tier (0-128) + // TODO: this should be part of MMContainer configuration + // TODO: we should allow having different memory containers + // for different tiers (for PMEM, we could use MM2Q) + double lowAllocationWatermark{100.0}; // if occupied space below, only allocate in upper tier + // if occupied space between, consult admission policy + // right now, random is supported + double highAllocationWatermark{100.0}; // if occupied space above, only allocate in lower tier + // we can still move items from PMEM to DRAM here + double evictionWatermark{0.0}; // starts eviction if below + uint64_t allowedDuplicatedItems{0}; // how many items can be in multiple tiers + friend CacheT; private: diff --git a/cachelib/cachebench/cache/Cache-inl.h b/cachelib/cachebench/cache/Cache-inl.h index 34f65e1b15..4bd245f69a 100644 --- a/cachelib/cachebench/cache/Cache-inl.h +++ b/cachelib/cachebench/cache/Cache-inl.h @@ -258,6 +258,15 @@ Cache::Cache(const CacheConfig& config, allocatorConfig_.cacheName = "cachebench"; + allocatorConfig_.admissionPolicy = config_.admissionPolicy; + allocatorConfig_.evictionPolicy = config_.evictionPolicy; + allocatorConfig_.promotionPolicy = config_.promotionPolicy; + allocatorConfig_.markUsefulChance = config_.markUsefulChance; + allocatorConfig_.lowAllocationWatermark = config_.lowAllocationWatermark; + allocatorConfig_.highAllocationWatermark = config_.highAllocationWatermark; + allocatorConfig_.evictionWatermark = config_.evictionWatermark; + allocatorConfig_.allowedDuplicatedItems = config_.allowedDuplicatedItems; + if (!allocatorConfig_.cacheDir.empty()) { cache_ = std::make_unique(Allocator::SharedMemNew, allocatorConfig_); diff --git a/cachelib/cachebench/util/CacheConfig.cpp b/cachelib/cachebench/util/CacheConfig.cpp index 2604744bd9..59a33cae8b 100644 --- a/cachelib/cachebench/util/CacheConfig.cpp +++ b/cachelib/cachebench/util/CacheConfig.cpp @@ -100,6 +100,15 @@ CacheConfig::CacheConfig(const folly::dynamic& configJson) { memoryTierConfigs.push_back(MemoryTierConfig(it).getMemoryTierCacheConfig()); } } + + JSONSetVal(configJson, admissionPolicy); + JSONSetVal(configJson, evictionPolicy); + JSONSetVal(configJson, promotionPolicy); + JSONSetVal(configJson, markUsefulChance); + JSONSetVal(configJson, lowAllocationWatermark); + JSONSetVal(configJson, highAllocationWatermark); + JSONSetVal(configJson, evictionWatermark); + JSONSetVal(configJson, allowedDuplicatedItems); // if you added new fields to the configuration, update the JSONSetVal // to make them available for the json configs and increment the size diff --git a/cachelib/cachebench/util/CacheConfig.h b/cachelib/cachebench/util/CacheConfig.h index f09d5966bd..5c95738103 100644 --- a/cachelib/cachebench/util/CacheConfig.h +++ b/cachelib/cachebench/util/CacheConfig.h @@ -283,6 +283,21 @@ struct CacheConfig : public JSONConfig { // this verifies whether the feature affects throughputs. bool enableItemDestructor{false}; + std::string admissionPolicy; // where to put allocated item + std::string evictionPolicy; // where to put evicted item (where in MMContainer?) + std::string promotionPolicy; // which item to promote + uint64_t markUsefulChance; // how to mark items as useful on lower tier + // TODO: this should be part of MMContainer configuration + // TODO: we should allow having different memory containers + // for different tiers (for PMEM, we could use MM2Q) + double lowAllocationWatermark; // if occupied space below, only allocate in upper tier + // if occupied space between, consult admission policy + // right now, random is supported + double highAllocationWatermark; // if occupied space above, only allocate in lower tier + // we can still move items from PMEM to DRAM here + double evictionWatermark; // starts eviction if below + uint64_t allowedDuplicatedItems; // how many items can be in multiple tiers + explicit CacheConfig(const folly::dynamic& configJson); CacheConfig() {}