2525#include < string>
2626
2727#include " cachelib/allocator/Cache.h"
28+ #include " cachelib/allocator/MemoryTierCacheConfig.h"
2829#include " cachelib/allocator/MM2Q.h"
2930#include " cachelib/allocator/MemoryMonitor.h"
3031#include " cachelib/allocator/NvmAdmissionPolicy.h"
@@ -49,6 +50,7 @@ class CacheAllocatorConfig {
4950 using NvmCacheDeviceEncryptor = typename CacheT::NvmCacheT::DeviceEncryptor;
5051 using MoveCb = typename CacheT::MoveCb;
5152 using NvmCacheConfig = typename CacheT::NvmCacheT::Config;
53+ using MemoryTierConfigs = std::vector<MemoryTierCacheConfig>;
5254 using Key = typename CacheT::Key;
5355 using EventTrackerSharedPtr = std::shared_ptr<typename CacheT::EventTracker>;
5456 using Item = typename CacheT::Item;
@@ -186,14 +188,23 @@ class CacheAllocatorConfig {
186188 // This allows cache to be persisted across restarts. One example use case is
187189 // to preserve the cache when releasing a new version of your service. Refer
188190 // to our user guide for how to set up cache persistence.
191+ // TODO: get rid of baseAddr or if set make sure all mapping are adjacent?
192+ // We can also make baseAddr a per-tier configuration
189193 CacheAllocatorConfig& enableCachePersistence (std::string directory,
190194 void * baseAddr = nullptr );
191195
192- // uses posix shm segments instead of the default sys-v shm segments.
193- // @throw std::invalid_argument if called without enabling
194- // cachePersistence()
196+ // Uses posix shm segments instead of the default sys-v shm
197+ // segments. @throw std::invalid_argument if called without enabling
198+ // cachePersistence().
195199 CacheAllocatorConfig& usePosixForShm ();
196200
201+ // Configures cache memory tiers. Accepts vector of MemoryTierCacheConfig.
202+ // Each vector element describes configuration for a single memory cache tier.
203+ CacheAllocatorConfig& configureMemoryTiers (const MemoryTierConfigs& configs);
204+
205+ // Return reference to MemoryTierCacheConfigs.
206+ const MemoryTierConfigs& getMemoryTierConfigs ();
207+
197208 // This turns on a background worker that periodically scans through the
198209 // access container and look for expired items and remove them.
199210 CacheAllocatorConfig& enableItemReaperInBackground (
@@ -541,6 +552,9 @@ class CacheAllocatorConfig {
541552 // cache.
542553 uint64_t nvmAdmissionMinTTL{0 };
543554
555+ // Configuration for memory tiers.
556+ MemoryTierConfigs memoryTierConfigs;
557+
544558 friend CacheT;
545559
546560 private:
@@ -801,6 +815,74 @@ CacheAllocatorConfig<T>& CacheAllocatorConfig<T>::enableItemReaperInBackground(
801815 return *this ;
802816}
803817
818+ template <typename T>
819+ CacheAllocatorConfig<T>& CacheAllocatorConfig<T>::configureMemoryTiers(
820+ const MemoryTierConfigs& config) {
821+ memoryTierConfigs = config;
822+ size_t sum_ratios = 0 ;
823+ size_t sum_sizes = 0 ;
824+
825+ for (auto tier_config: memoryTierConfigs) {
826+ auto tier_size = tier_config.getSize ();
827+ auto tier_ratio = tier_config.getRatio ();
828+ if ((!tier_size and !tier_ratio) || (tier_size and tier_ratio)) {
829+ throw std::invalid_argument (
830+ " For each memory tier either size or ratio must be set." );
831+ }
832+ sum_ratios += tier_ratio;
833+ sum_sizes += tier_size;
834+ }
835+
836+ if (sum_ratios) {
837+ if (!getCacheSize ()) {
838+ throw std::invalid_argument (
839+ " Total cache size must be specified when size ratios are \
840+ used to specify memory tier sizes." );
841+ } else {
842+ if (getCacheSize () < sum_ratios) {
843+ throw std::invalid_argument (
844+ " Sum of all tier size ratios is greater than total cache size." );
845+ }
846+ // Convert ratios to sizes
847+ sum_sizes = 0 ;
848+ size_t partition_size = getCacheSize () / sum_ratios;
849+ for (auto & tier_config: memoryTierConfigs) {
850+ tier_config.setSize (partition_size * tier_config.getRatio ());
851+ sum_sizes += tier_config.getSize ();
852+ }
853+ if (getCacheSize () != sum_sizes) {
854+ // Adjust capacity of the last tier to account for rounding error
855+ memoryTierConfigs.back ().setSize (memoryTierConfigs.back ().getSize () + \
856+ (getCacheSize () - sum_sizes));
857+ sum_sizes = getCacheSize ();
858+ }
859+ }
860+ } else if (sum_sizes) {
861+ if (getCacheSize () && sum_sizes != getCacheSize ()) {
862+ throw std::invalid_argument (
863+ " Sum of tier sizes doesn't match total cache size. \
864+ Setting of cache total size is not required when per-tier \
865+ sizes are specified - it is calculated as sum of tier sizes." );
866+ }
867+ } else {
868+ throw std::invalid_argument (
869+ " Either sum of all memory tiers sizes or sum of all ratios \
870+ must be greater than 0." );
871+ }
872+
873+ if (sum_sizes && !getCacheSize ()) {
874+ setCacheSize (sum_sizes);
875+ }
876+
877+ return *this ;
878+ }
879+
880+ // const std::vector<MemoryTierCacheConfig>& CacheAllocatorConfig<T>::getMemoryTierConfigs() {
881+ template <typename T>
882+ const typename CacheAllocatorConfig<T>::MemoryTierConfigs& CacheAllocatorConfig<T>::getMemoryTierConfigs() {
883+ return memoryTierConfigs;
884+ }
885+
804886template <typename T>
805887CacheAllocatorConfig<T>& CacheAllocatorConfig<T>::disableCacheEviction() {
806888 disableEviction = true ;
@@ -970,7 +1052,7 @@ std::map<std::string, std::string> CacheAllocatorConfig<T>::serialize() const {
9701052
9711053 configMap[" size" ] = std::to_string (size);
9721054 configMap[" cacheDir" ] = cacheDir;
973- configMap[" posixShm" ] = usePosixShm ? " set" : " empty" ;
1055+ configMap[" posixShm" ] = isUsingPosixShm () ? " set" : " empty" ;
9741056
9751057 configMap[" defaultAllocSizes" ] = " " ;
9761058 // Stringify std::set
0 commit comments