25
25
#include < string>
26
26
27
27
#include " cachelib/allocator/Cache.h"
28
+ #include " cachelib/allocator/MemoryTierCacheConfig.h"
28
29
#include " cachelib/allocator/MM2Q.h"
29
30
#include " cachelib/allocator/MemoryMonitor.h"
30
31
#include " cachelib/allocator/NvmAdmissionPolicy.h"
@@ -49,6 +50,7 @@ class CacheAllocatorConfig {
49
50
using NvmCacheDeviceEncryptor = typename CacheT::NvmCacheT::DeviceEncryptor;
50
51
using MoveCb = typename CacheT::MoveCb;
51
52
using NvmCacheConfig = typename CacheT::NvmCacheT::Config;
53
+ using MemoryTierConfigs = std::vector<MemoryTierCacheConfig>;
52
54
using Key = typename CacheT::Key;
53
55
using EventTrackerSharedPtr = std::shared_ptr<typename CacheT::EventTracker>;
54
56
using Item = typename CacheT::Item;
@@ -186,14 +188,23 @@ class CacheAllocatorConfig {
186
188
// This allows cache to be persisted across restarts. One example use case is
187
189
// to preserve the cache when releasing a new version of your service. Refer
188
190
// 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
189
193
CacheAllocatorConfig& enableCachePersistence (std::string directory,
190
194
void * baseAddr = nullptr );
191
195
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().
195
199
CacheAllocatorConfig& usePosixForShm ();
196
200
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
+
197
208
// This turns on a background worker that periodically scans through the
198
209
// access container and look for expired items and remove them.
199
210
CacheAllocatorConfig& enableItemReaperInBackground (
@@ -541,6 +552,9 @@ class CacheAllocatorConfig {
541
552
// cache.
542
553
uint64_t nvmAdmissionMinTTL{0 };
543
554
555
+ // Configuration for memory tiers.
556
+ MemoryTierConfigs memoryTierConfigs;
557
+
544
558
friend CacheT;
545
559
546
560
private:
@@ -801,6 +815,74 @@ CacheAllocatorConfig<T>& CacheAllocatorConfig<T>::enableItemReaperInBackground(
801
815
return *this ;
802
816
}
803
817
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
+
804
886
template <typename T>
805
887
CacheAllocatorConfig<T>& CacheAllocatorConfig<T>::disableCacheEviction() {
806
888
disableEviction = true ;
@@ -970,7 +1052,7 @@ std::map<std::string, std::string> CacheAllocatorConfig<T>::serialize() const {
970
1052
971
1053
configMap[" size" ] = std::to_string (size);
972
1054
configMap[" cacheDir" ] = cacheDir;
973
- configMap[" posixShm" ] = usePosixShm ? " set" : " empty" ;
1055
+ configMap[" posixShm" ] = isUsingPosixShm () ? " set" : " empty" ;
974
1056
975
1057
configMap[" defaultAllocSizes" ] = " " ;
976
1058
// Stringify std::set
0 commit comments