@@ -405,9 +405,22 @@ CacheAllocator<CacheTrait>::allocateInternalTier(TierId tid,
405405 // TODO: per-tier
406406 (*stats_.allocAttempts )[pid][cid].inc ();
407407
408- void * memory = allocator_[tid]->allocate (pid, requiredSize);
408+ void *memory = nullptr ;
409+
410+ if (tid == 0 && config_.acTopTierEvictionWatermark > 0.0
411+ && getAllocationClassStats (tid, pid, cid)
412+ .approxFreePercent < config_.acTopTierEvictionWatermark ) {
413+ memory = findEviction (tid, pid, cid);
414+ }
415+
416+ if (memory == nullptr ) {
417+ // TODO: should we try allocate item even if this will result in violating
418+ // acTopTierEvictionWatermark?
419+ memory = allocator_[tid]->allocate (pid, requiredSize);
420+ }
421+
409422 // TODO: Today disableEviction means do not evict from memory (DRAM).
410- // Should we support eviction between memory tiers (e.g. from DRAM to PMEM )?
423+ // Should we support eviction between memory tiers (e.g. from DRAM to next tier )?
411424 if (memory == nullptr && !config_.isEvictionDisabled ()) {
412425 memory = findEviction (tid, pid, cid);
413426 }
@@ -448,19 +461,71 @@ CacheAllocator<CacheTrait>::allocateInternalTier(TierId tid,
448461 return handle;
449462}
450463
464+ template <typename CacheTrait>
465+ TierId
466+ CacheAllocator<CacheTrait>::getTargetTierForItem(PoolId pid,
467+ typename Item::Key key,
468+ uint32_t size,
469+ uint32_t creationTime,
470+ uint32_t expiryTime) {
471+ if (getNumTiers () == 1 )
472+ return 0 ;
473+
474+ if (config_.forceAllocationTier != UINT64_MAX) {
475+ return config_.forceAllocationTier ;
476+ }
477+
478+ const TierId defaultTargetTier = 0 ;
479+
480+ const auto requiredSize = Item::getRequiredSize (key, size);
481+ const auto cid = allocator_[defaultTargetTier]->getAllocationClassId (pid, requiredSize);
482+
483+ auto freePercentage = getAllocationClassStats (defaultTargetTier, pid, cid).approxFreePercent ;
484+
485+ // TODO: COULD we implement BG worker which would move slabs around
486+ // so that there is similar amount of free space in each pool/ac.
487+ // Should this be responsibility of BG evictor?
488+
489+ if (freePercentage >= config_.maxAcAllocationWatermark )
490+ return defaultTargetTier;
491+
492+ if (freePercentage <= config_.minAcAllocationWatermark )
493+ return defaultTargetTier + 1 ;
494+
495+ // TODO: we can even think about creating different allocation classes for different tiers
496+ // and we could look at possible fragmentation when deciding where to put the item
497+ if (config_.sizeThresholdPolicy )
498+ return requiredSize < config_.sizeThresholdPolicy ? defaultTargetTier : defaultTargetTier + 1 ;
499+
500+ // TODO: (e.g. always put chained items to PMEM)
501+ // if (chainedItemsPolicy)
502+ // return item.isChainedItem() ? defaultTargetTier + 1 : defaultTargetTier;
503+
504+ // TODO:
505+ // if (expiryTimePolicy)
506+ // return (expiryTime - creationTime) < expiryTimePolicy ? defaultTargetTier : defaultTargetTier + 1;
507+
508+ // TODO:
509+ // if (keyPolicy) // this can be based on key length or some other properties
510+ // return getTargetTierForKey(key);
511+
512+ // TODO:
513+ // if (compressabilityPolicy) // if compresses well store in PMEM? latency will be higher anyway
514+ // return TODO;
515+
516+ // TODO: only works for 2 tiers
517+ return (folly::Random::rand32 () % 100 ) < config_.defaultTierChancePercentage ? defaultTargetTier : defaultTargetTier + 1 ;
518+ }
519+
451520template <typename CacheTrait>
452521typename CacheAllocator<CacheTrait>::WriteHandle
453522CacheAllocator<CacheTrait>::allocateInternal(PoolId pid,
454523 typename Item::Key key,
455524 uint32_t size,
456525 uint32_t creationTime,
457526 uint32_t expiryTime) {
458- auto tid = 0 ; /* TODO: consult admission policy */
459- for (TierId tid = 0 ; tid < getNumTiers (); ++tid) {
460- auto handle = allocateInternalTier (tid, pid, key, size, creationTime, expiryTime);
461- if (handle) return handle;
462- }
463- return {};
527+ auto tid = getTargetTierForItem (pid, key, size, creationTime, expiryTime);
528+ return allocateInternalTier (tid, pid, key, size, creationTime, expiryTime);
464529}
465530
466531template <typename CacheTrait>
@@ -1636,6 +1701,13 @@ bool CacheAllocator<CacheTrait>::shouldWriteToNvmCacheExclusive(
16361701 return true ;
16371702}
16381703
1704+ template <typename CacheTrait>
1705+ bool CacheAllocator<CacheTrait>::shouldEvictToNextMemoryTier(
1706+ TierId sourceTierId, TierId targetTierId, PoolId pid, Item& item)
1707+ {
1708+ return !(config_.disableEvictionToMemory );
1709+ }
1710+
16391711template <typename CacheTrait>
16401712typename CacheAllocator<CacheTrait>::WriteHandle
16411713CacheAllocator<CacheTrait>::tryEvictToNextMemoryTier(
@@ -1649,8 +1721,10 @@ CacheAllocator<CacheTrait>::tryEvictToNextMemoryTier(
16491721 if (handle) { return handle; }
16501722 }
16511723
1652- TierId nextTier = tid; // TODO - calculate this based on some admission policy
1724+ TierId nextTier = tid;
16531725 while (++nextTier < getNumTiers ()) { // try to evict down to the next memory tiers
1726+ if (!shouldEvictToNextMemoryTier (tid, nextTier, pid, item))
1727+ continue ;
16541728 // allocateInternal might trigger another eviction
16551729 auto newItemHdl = allocateInternalTier (nextTier, pid,
16561730 item.getKey (),
@@ -2431,6 +2505,10 @@ void CacheAllocator<CacheTrait>::createMMContainers(const PoolId pid,
24312505 .getAllocsPerSlab ()
24322506 : 0 );
24332507 for (TierId tid = 0 ; tid < getNumTiers (); tid++) {
2508+ if constexpr (std::is_same_v<MMConfig, MMLru::Config> || std::is_same_v<MMConfig, MM2Q::Config>) {
2509+ config.lruInsertionPointSpec = config_.memoryTierConfigs [tid].lruInsertionPointSpec ;
2510+ config.markUsefulChance = config_.memoryTierConfigs [tid].markUsefulChance ;
2511+ }
24342512 mmContainers_[tid][pid][cid].reset (new MMContainer (config, compressor_));
24352513 }
24362514 }
@@ -2485,7 +2563,7 @@ std::set<PoolId> CacheAllocator<CacheTrait>::getRegularPoolIds() const {
24852563 folly::SharedMutex::ReadHolder r (poolsResizeAndRebalanceLock_);
24862564 // TODO - get rid of the duplication - right now, each tier
24872565 // holds pool objects with mostly the same info
2488- return filterCompactCachePools (allocator_[0 ]->getPoolIds ());
2566+ return filterCompactCachePools (allocator_[currentTier () ]->getPoolIds ());
24892567}
24902568
24912569template <typename CacheTrait>
0 commit comments