cachelib/allocator/Cache.h (98 lines of code) (raw):

/* * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <gtest/gtest_prod.h> #include <mutex> #include <unordered_map> #include "cachelib/allocator/CacheDetails.h" #include "cachelib/allocator/CacheStats.h" #include "cachelib/allocator/ICompactCache.h" #include "cachelib/allocator/memory/MemoryAllocator.h" #include "cachelib/common/Hash.h" namespace facebook { namespace cachelib { class PoolResizer; class PoolRebalancer; class PoolOptimizer; class MemoryMonitor; // Forward declaration. class RebalanceStrategy; class PoolOptimizeStrategy; class MarginalHitsOptimizeStrategy; class AllocatorConfigExporter; namespace tests { struct SimplePoolOptimizeStrategy; } // The mode in which the cache was accessed. This can be used by containers // to differentiate between the access modes and do appropriate action. enum class AccessMode { kRead, kWrite }; // used by RemoveCB, indicating if the removal from the MMContainer was an // eviction or not. enum class RemoveContext { kEviction, kNormal }; // used by ItemDestructor, indicating how the item is destructed enum class DestructorContext { // item was in dram and evicted from dram. it could have // been present in nvm as well. kEvictedFromRAM, // item was only in nvm and evicted from nvm kEvictedFromNVM, // item was present in dram and removed by user calling // remove()/insertOrReplace, or removed due to expired. // it could have been present in nvm as well. kRemovedFromRAM, // item was present only in nvm and removed by user calling // remove()/insertOrReplace. kRemovedFromNVM }; // A base class of cache exposing members and status agnostic of template type. class CacheBase { public: CacheBase() = default; virtual ~CacheBase() = default; // Movable but not copyable CacheBase(const CacheBase&) = delete; CacheBase& operator=(const CacheBase&) = delete; CacheBase(CacheBase&&) = default; CacheBase& operator=(CacheBase&&) = default; // Get a string referring to the cache name for this cache virtual const std::string getCacheName() const = 0; // Get the reference to a memory pool, for stats purposes // // @param poolId The pool id to query virtual const MemoryPool& getPool(PoolId poolId) const = 0; // Get Pool specific stats (regular pools). This includes stats from the // Memory Pool and also the cache. // // @param poolId the pool id virtual PoolStats getPoolStats(PoolId poolId) const = 0; // @param poolId the pool id virtual AllSlabReleaseEvents getAllSlabReleaseEvents(PoolId poolId) const = 0; // This can be expensive so it is not part of PoolStats // // @param pid pool id // @param slabProjectionLength number of slabs worth of items to visit to // estimate the projected age. If 0, returns // tail age for projection age. // // @return PoolEvictionAgeStats see CacheStats.h virtual PoolEvictionAgeStats getPoolEvictionAgeStats( PoolId pid, unsigned int slabProjectionLength) const = 0; // @return a map of <stat name -> stat value> representation for all the nvm // cache stats. This is useful for our monitoring to directly upload them. virtual std::unordered_map<std::string, double> getNvmCacheStatsMap() const = 0; // @return a map of <stat name -> stat value> representation for all the event // tracker stats. If no event tracker exists, this will be empty virtual std::unordered_map<std::string, uint64_t> getEventTrackerStatsMap() const = 0; // @return the Cache metadata virtual CacheMetadata getCacheMetadata() const noexcept = 0; // @return cache's memory usage stats virtual CacheMemoryStats getCacheMemoryStats() const = 0; // @return the overall cache stats virtual GlobalCacheStats getGlobalCacheStats() const = 0; // @return the slab release stats. virtual SlabReleaseStats getSlabReleaseStats() const = 0; // Set rebalancing strategy // // @param pid Pool id of the pool to set this strategy on. // @param strategy The strategy void setRebalanceStrategy(PoolId pid, std::shared_ptr<RebalanceStrategy> strategy); // @param pid The pool id. // // @return The rebalancing strategy of the specifid pool. std::shared_ptr<RebalanceStrategy> getRebalanceStrategy(PoolId pid) const; // Set resizing strategy // // @param pid Pool id of the pool to set this strategy on. // @param strategy The strategy void setResizeStrategy(PoolId pid, std::shared_ptr<RebalanceStrategy> strategy); // @param pid The pool id. // // @return The resizing strategy of the specifid pool. std::shared_ptr<RebalanceStrategy> getResizeStrategy(PoolId pid) const; // Set optimizing strategy // // @param pid Pool id of the pool to set this strategy on. // @param strategy The strategy void setPoolOptimizeStrategy(std::shared_ptr<PoolOptimizeStrategy> strategy); // @param pid The pool id. // // @return The optimizing strategy of the specifid pool. std::shared_ptr<PoolOptimizeStrategy> getPoolOptimizeStrategy() const; // return the list of currently active pools that are oversized virtual std::set<PoolId> getRegularPoolIdsForResize() const = 0; // return a list of all valid pool ids. virtual std::set<PoolId> getPoolIds() const = 0; // returns a list of pools excluding compact cache pools virtual std::set<PoolId> getRegularPoolIds() const = 0; // returns a list of pools created for ccache. virtual std::set<PoolId> getCCachePoolIds() const = 0; // return whether a pool participates in auto-resizing virtual bool autoResizeEnabledForPool(PoolId) const = 0; // return the virtual interface of an attached compact cache for a particular // pool id virtual const ICompactCache& getCompactCache(PoolId pid) const = 0; protected: // move bytes from one pool to another. The source pool should be at least // _bytes_ in size. // // // @param src the pool to be sized down and giving the memory. // @param dest the pool receiving the memory. // @param bytes the number of bytes to move from src to dest. // @param true if the resize succeeded. false if src does does not have // correct size to do the transfer. // @throw std::invalid_argument if src or dest is invalid pool virtual bool resizePools(PoolId /* src */, PoolId /* dest */, size_t /* bytes */) = 0; // resize all of the attached and disabled compact caches virtual void resizeCompactCaches() = 0; // serialize cache allocator config for exporting to Scuba virtual std::map<std::string, std::string> serializeConfigParams() const = 0; // Releases a slab from a pool into its corresponding memory pool // or back to the slab allocator, depending on SlabReleaseMode. // SlabReleaseMode::kRebalance -> back to the pool // SlabReleaseMode::kResize -> back to the slab allocator // // @param pid Pool that will make make one slab available // @param cid Class that will release a slab back to its pool // or slab allocator // @param mode the mode for slab release (rebalance/resize) // @param hint hint referring to the slab. this can be an allocation // that the user knows to exist in the slab. If this is // nullptr, a random slab is selected from the pool and // allocation class. // // @throw std::invalid_argument if the hint is invalid or if the pid or cid // is invalid. virtual void releaseSlab(PoolId pid, ClassId cid, SlabReleaseMode mode, const void* hint = nullptr) = 0; // update the number of slabs to be advised virtual void updateNumSlabsToAdvise(int32_t numSlabsToAdvise) = 0; // calculate the number of slabs to be advised/reclaimed in each pool virtual PoolAdviseReclaimData calcNumSlabsToAdviseReclaim() = 0; // Releasing a slab from this allocation class id and pool id. The release // could be for a pool resizing or allocation class rebalancing. // // All active allocations will be evicted in the process. // // This function will be blocked until a slab is freed // // @param pid Pool that will make one slab available // @param victim Class that will release a slab back to its pool // or slab allocator or a receiver if defined // @param receiver Class that will receive // @param mode the mode for slab release (rebalance/resize) // the user knows to exist in the slab. If this is nullptr, // a random slab is selected from the pool and allocation // class. // @param hint hint referring to the slab. this can be an allocation // that the user knows to exist in the slab. If this is // nullptr, a random slab is selected from the pool and // allocation class. // // @throw std::invalid_argument if the hint is invalid or if the pid or cid // is invalid. virtual void releaseSlab(PoolId pid, ClassId victim, ClassId receiver, SlabReleaseMode mode, const void* hint = nullptr) = 0; // Reclaim slabs from the slab allocator that were advised away using // releaseSlab in SlabReleaseMode::kAdvise mode. // // @param pid The pool for which to recliam slabs // @param numSlabs The number of slabs to reclaim for the pool // @return The number of slabs that were actually reclaimed (<= numSlabs) virtual unsigned int reclaimSlabs(PoolId id, size_t numSlabs) = 0; // Protect 'poolRebalanceStragtegies_' and `poolResizeStrategies_` // and `poolOptimizeStrategy_` mutable std::mutex lock_; std::unordered_map<PoolId, std::shared_ptr<RebalanceStrategy>> poolRebalanceStrategies_; std::unordered_map<PoolId, std::shared_ptr<RebalanceStrategy>> poolResizeStrategies_; std::shared_ptr<PoolOptimizeStrategy> poolOptimizeStrategy_; friend PoolResizer; friend PoolRebalancer; friend PoolOptimizer; friend MemoryMonitor; friend AllocatorConfigExporter; }; } // namespace cachelib } // namespace facebook