1515 */  
1616
1717#include  < numeric> 
18+ 
1819#include  " cachelib/allocator/CacheAllocator.h" 
1920#include  " cachelib/allocator/tests/TestBase.h" 
2021
2122namespace  facebook  {
2223namespace  cachelib  {
2324namespace  tests  {
2425
25- 
2626using  LruAllocatorConfig = CacheAllocatorConfig<LruAllocator>;
2727using  LruMemoryTierConfigs = LruAllocatorConfig::MemoryTierConfigs;
2828using  Strings = std::vector<std::string>;
@@ -34,64 +34,96 @@ const std::string defaultCacheDir{"/var/metadataDir"};
3434const  std::string defaultPmemPath{" /dev/shm/p1" 
3535const  std::string defaultDaxPath{" /dev/dax0.0" 
3636
37+ const  size_t  metaDataSize = 4194304 ;
38+ constexpr  size_t  MB = 1024ULL  * 1024ULL ;
39+ constexpr  size_t  GB = MB * 1024ULL ;
40+ 
3741template  <typename  Allocator>
38- class  MemoryTiersTest : public  AllocatorTest <Allocator> {
39-   public: 
40-     void  basicCheck (
41-         LruAllocatorConfig& actualConfig,
42-         const  Strings& expectedPaths = {defaultPmemPath},
43-         size_t  expectedTotalCacheSize = defaultTotalCacheSize,
44-         const  std::string& expectedCacheDir = defaultCacheDir) {
45-       EXPECT_EQ (actualConfig.getCacheSize (), expectedTotalCacheSize);
46-       EXPECT_EQ (actualConfig.getMemoryTierConfigs ().size (), expectedPaths.size ());
47-       EXPECT_EQ (actualConfig.getCacheDir (), expectedCacheDir);
48-       auto  configs = actualConfig.getMemoryTierConfigs ();
49- 
50-       size_t  sum_sizes = std::accumulate (configs.begin (), configs.end (), 0 ,
51-           [](const  size_t  i, const  MemoryTierCacheConfig& config) { return  i + config.getSize ();});
52-       size_t  sum_ratios = std::accumulate (configs.begin (), configs.end (), 0 ,
53-           [](const  size_t  i, const  MemoryTierCacheConfig& config) { return  i + config.getRatio ();});
54- 
55-       size_t  partition_size = 0 ;
56-       if  (sum_ratios) {
57-         partition_size = actualConfig.getCacheSize () / sum_ratios;
58-         /*  Sum of sizes can be lower due to rounding down to partition_size. */ 
59-         EXPECT_GE (sum_sizes, expectedTotalCacheSize - partition_size);
60-       }
42+ class  MemoryTiersTest  : public  AllocatorTest <Allocator> {
43+  public: 
44+   void  basicCheck (LruAllocatorConfig& actualConfig,
45+                   const  Strings& expectedPaths = {defaultPmemPath},
46+                   size_t  expectedTotalCacheSize = defaultTotalCacheSize,
47+                   const  std::string& expectedCacheDir = defaultCacheDir) {
48+     EXPECT_EQ (actualConfig.getCacheSize (), expectedTotalCacheSize);
49+     EXPECT_EQ (actualConfig.getMemoryTierConfigs ().size (), expectedPaths.size ());
50+     EXPECT_EQ (actualConfig.getCacheDir (), expectedCacheDir);
51+     auto  configs = actualConfig.getMemoryTierConfigs ();
6152
62-       for (auto  i = 0 ; i < configs.size (); ++i) {
63-         auto  &opt = std::get<FileShmSegmentOpts>(configs[i].getShmTypeOpts ());
64-         EXPECT_EQ (opt.path , expectedPaths[i]);
65-         EXPECT_GT (configs[i].getSize (), 0 );
66-         if  (configs[i].getRatio () && (i < configs.size () - 1 )) {
67-           EXPECT_EQ (configs[i].getSize (), partition_size * configs[i].getRatio ());
68-         }
69-       }
53+     size_t  sum_sizes = std::accumulate (
54+         configs.begin (), configs.end (), 0 ,
55+         [](const  size_t  i, const  MemoryTierCacheConfig& config) {
56+           return  i + config.getSize ();
57+         });
58+     size_t  sum_ratios = std::accumulate (
59+         configs.begin (), configs.end (), 0 ,
60+         [](const  size_t  i, const  MemoryTierCacheConfig& config) {
61+           return  i + config.getRatio ();
62+         });
63+ 
64+     size_t  partition_size = 0 ;
65+     if  (sum_ratios) {
66+       partition_size = actualConfig.getCacheSize () / sum_ratios;
67+       /*  Sum of sizes can be lower due to rounding down to partition_size. */ 
68+       EXPECT_GE (sum_sizes, expectedTotalCacheSize - partition_size);
7069    }
7170
72-     LruAllocatorConfig createTestCacheConfig (
73-         const  Strings& tierPaths = {defaultPmemPath},
74-         const  SizePairs& sizePairs = {std::make_tuple (1  /*  ratio */ 0  /*  size */ 
75-         bool  setPosixForShm = true ,
76-         size_t  cacheSize = defaultTotalCacheSize,
77-         const  std::string& cacheDir = defaultCacheDir) {
78-       LruAllocatorConfig cfg;
79-       cfg.setCacheSize (cacheSize)
80-          .enableCachePersistence (cacheDir);
81- 
82-       if  (setPosixForShm)
83-          cfg.usePosixForShm ();
84- 
85-       LruMemoryTierConfigs tierConfigs;
86-       tierConfigs.reserve (tierPaths.size ());
87-       for (auto  i = 0 ; i < tierPaths.size (); ++i) {
88-         tierConfigs.push_back (MemoryTierCacheConfig::fromFile (tierPaths[i])
89-                               .setRatio (std::get<0 >(sizePairs[i]))
90-                               .setSize (std::get<1 >(sizePairs[i])));
71+     for  (auto  i = 0 ; i < configs.size (); ++i) {
72+       auto & opt = std::get<FileShmSegmentOpts>(configs[i].getShmTypeOpts ());
73+       EXPECT_EQ (opt.path , expectedPaths[i]);
74+       EXPECT_GT (configs[i].getSize (), 0 );
75+       if  (configs[i].getRatio () && (i < configs.size () - 1 )) {
76+         EXPECT_EQ (configs[i].getSize (), partition_size * configs[i].getRatio ());
9177      }
92-       cfg.configureMemoryTiers (tierConfigs);
93-       return  cfg;
9478    }
79+   }
80+ 
81+   LruAllocatorConfig createTestCacheConfig (
82+       const  Strings& tierPaths = {defaultPmemPath},
83+       const  SizePairs& sizePairs = {std::make_tuple (1  /*  ratio */ 
84+                                                     0  /*  size */ 
85+       bool  setPosixForShm = true ,
86+       size_t  cacheSize = defaultTotalCacheSize,
87+       const  std::string& cacheDir = defaultCacheDir) {
88+     LruAllocatorConfig cfg;
89+     cfg.setCacheSize (cacheSize).enableCachePersistence (cacheDir);
90+ 
91+     if  (setPosixForShm)
92+       cfg.usePosixForShm ();
93+ 
94+     LruMemoryTierConfigs tierConfigs;
95+     tierConfigs.reserve (tierPaths.size ());
96+     for  (auto  i = 0 ; i < tierPaths.size (); ++i) {
97+       tierConfigs.push_back (MemoryTierCacheConfig::fromFile (tierPaths[i])
98+                                 .setRatio (std::get<0 >(sizePairs[i]))
99+                                 .setSize (std::get<1 >(sizePairs[i])));
100+     }
101+     cfg.configureMemoryTiers (tierConfigs);
102+     return  cfg;
103+   }
104+ 
105+   LruAllocatorConfig createTieredCacheConfig (size_t  totalCacheSize,
106+                                              size_t  numTiers = 2 ) {
107+     LruAllocatorConfig tieredCacheConfig{};
108+     std::vector<MemoryTierCacheConfig> configs;
109+     for  (auto  i = 1 ; i <= numTiers; ++i) {
110+       configs.push_back (MemoryTierCacheConfig::fromFile (
111+                             folly::sformat (" /tmp/tier{}-{}" getpid ()))
112+                             .setRatio (1 ));
113+     }
114+     tieredCacheConfig.setCacheSize (totalCacheSize)
115+         .enableCachePersistence (
116+             folly::sformat (" /tmp/multi-tier-test/{}" getpid ()))
117+         .usePosixForShm ()
118+         .configureMemoryTiers (configs);
119+     return  tieredCacheConfig;
120+   }
121+ 
122+   LruAllocatorConfig createDramCacheConfig (size_t  totalCacheSize) {
123+     LruAllocatorConfig dramConfig{};
124+     dramConfig.setCacheSize (totalCacheSize);
125+     return  dramConfig;
126+   }
95127};
96128
97129using  LruMemoryTiersTest = MemoryTiersTest<LruAllocator>;
@@ -107,77 +139,118 @@ TEST_F(LruMemoryTiersTest, TestValid1TierDaxRatioConfig) {
107139}
108140
109141TEST_F (LruMemoryTiersTest, TestValid1TierDaxSizeConfig) {
110-   LruAllocatorConfig cfg = createTestCacheConfig ({defaultDaxPath},
111-                                                  {std::make_tuple (0 , defaultTotalCacheSize)},
112-                                                  /*  setPosixShm */ true ,
113-                                                  /*  cacheSize */ 0 );
142+   LruAllocatorConfig cfg =
143+       createTestCacheConfig ({defaultDaxPath},
144+                             {std::make_tuple (0 , defaultTotalCacheSize)},
145+                             /*  setPosixShm */ true ,
146+                             /*  cacheSize */ 0 );
114147  basicCheck (cfg, {defaultDaxPath});
115148
116149  //  Setting size after conifguringMemoryTiers with sizes is not allowed.
117-   EXPECT_THROW (cfg.setCacheSize (defaultTotalCacheSize + 1 ), std::invalid_argument);
150+   EXPECT_THROW (cfg.setCacheSize (defaultTotalCacheSize + 1 ),
151+                std::invalid_argument);
118152}
119153
120154TEST_F (LruMemoryTiersTest, TestValid2TierDaxPmemConfig) {
121-   LruAllocatorConfig cfg = createTestCacheConfig ({defaultDaxPath, defaultPmemPath},
122-                                                  {std::make_tuple (1 , 0 ), std::make_tuple (1 , 0 )});
155+   LruAllocatorConfig cfg =
156+       createTestCacheConfig ({defaultDaxPath, defaultPmemPath},
157+                             {std::make_tuple (1 , 0 ), std::make_tuple (1 , 0 )});
123158  basicCheck (cfg, {defaultDaxPath, defaultPmemPath});
124159}
125160
126161TEST_F (LruMemoryTiersTest, TestValid2TierDaxPmemRatioConfig) {
127-   LruAllocatorConfig cfg = createTestCacheConfig ({defaultDaxPath, defaultPmemPath},
128-                                                  {std::make_tuple (5 , 0 ), std::make_tuple (2 , 0 )});
162+   LruAllocatorConfig cfg =
163+       createTestCacheConfig ({defaultDaxPath, defaultPmemPath},
164+                             {std::make_tuple (5 , 0 ), std::make_tuple (2 , 0 )});
129165  basicCheck (cfg, {defaultDaxPath, defaultPmemPath});
130166}
131167
132168TEST_F (LruMemoryTiersTest, TestValid2TierDaxPmemSizeConfig) {
133169  size_t  size_1 = 4321 , size_2 = 1234 ;
134-   LruAllocatorConfig cfg = createTestCacheConfig ({defaultDaxPath, defaultPmemPath}, 
135-                                                  { std::make_tuple ( 0 , size_1),  std::make_tuple ( 0 , size_2) },
136-                                                   true , 0 );
170+   LruAllocatorConfig cfg = createTestCacheConfig (
171+       {defaultDaxPath, defaultPmemPath },
172+       { std::make_tuple ( 0 , size_1),  std::make_tuple ( 0 , size_2)},  true , 0 );
137173  basicCheck (cfg, {defaultDaxPath, defaultPmemPath}, size_1 + size_2);
138174
139175  //  Setting size after conifguringMemoryTiers with sizes is not allowed.
140176  EXPECT_THROW (cfg.setCacheSize (size_1 + size_2 + 1 ), std::invalid_argument);
141177}
142178
143179TEST_F (LruMemoryTiersTest, TestInvalid2TierConfigPosixShmNotSet) {
144-   LruAllocatorConfig cfg = createTestCacheConfig ({defaultDaxPath, defaultPmemPath},
145-                                                  {std::make_tuple (1 , 0 ), std::make_tuple (1 , 0 )},
146-                                                   /*  setPosixShm */ false );
180+   LruAllocatorConfig cfg =
181+       createTestCacheConfig ({defaultDaxPath, defaultPmemPath},
182+                             {std::make_tuple (1 , 0 ), std::make_tuple (1 , 0 )},
183+                             /*  setPosixShm */ false );
147184}
148185
149186TEST_F (LruMemoryTiersTest, TestInvalid2TierConfigNumberOfPartitionsTooLarge) {
150187  EXPECT_THROW (createTestCacheConfig ({defaultDaxPath, defaultPmemPath},
151-                                      {std::make_tuple (defaultTotalCacheSize, 0 ), std::make_tuple (1 , 0 )}).validate (),
188+                                      {std::make_tuple (defaultTotalCacheSize, 0 ),
189+                                       std::make_tuple (1 , 0 )})
190+                    .validate (),
152191               std::invalid_argument);
153192}
154193
155194TEST_F (LruMemoryTiersTest, TestInvalid2TierConfigSizesAndRatiosMixed) {
156-   EXPECT_THROW (createTestCacheConfig ({defaultDaxPath, defaultPmemPath},
157-                                      {std::make_tuple (1 , 0 ), std::make_tuple (1 , 1 )}),
158-                std::invalid_argument);
159-   EXPECT_THROW (createTestCacheConfig ({defaultDaxPath, defaultPmemPath},
160-                                      {std::make_tuple (1 , 1 ), std::make_tuple (0 , 1 )}),
161-                std::invalid_argument);
195+   EXPECT_THROW (
196+       createTestCacheConfig ({defaultDaxPath, defaultPmemPath},
197+                             {std::make_tuple (1 , 0 ), std::make_tuple (1 , 1 )}),
198+       std::invalid_argument);
199+   EXPECT_THROW (
200+       createTestCacheConfig ({defaultDaxPath, defaultPmemPath},
201+                             {std::make_tuple (1 , 1 ), std::make_tuple (0 , 1 )}),
202+       std::invalid_argument);
162203}
163204
164205TEST_F (LruMemoryTiersTest, TestInvalid2TierConfigSizesAndRatioNotSet) {
165-   EXPECT_THROW (createTestCacheConfig ({defaultDaxPath, defaultPmemPath},
166-                                      {std::make_tuple (1 , 0 ), std::make_tuple (0 , 0 )}),
167-                std::invalid_argument);
206+   EXPECT_THROW (
207+       createTestCacheConfig ({defaultDaxPath, defaultPmemPath},
208+                             {std::make_tuple (1 , 0 ), std::make_tuple (0 , 0 )}),
209+       std::invalid_argument);
168210}
169211
170212TEST_F (LruMemoryTiersTest, TestInvalid2TierConfigRatiosCacheSizeNotSet) {
171-   EXPECT_THROW (createTestCacheConfig ({defaultDaxPath, defaultPmemPath},
172-                                      {std::make_tuple (1 , 0 ), std::make_tuple (1 , 0 )},
173-                                      /*  setPosixShm */ true , /*  cacheSize */ 0 ).validate (),
174-                std::invalid_argument);
213+   EXPECT_THROW (
214+       createTestCacheConfig ({defaultDaxPath, defaultPmemPath},
215+                             {std::make_tuple (1 , 0 ), std::make_tuple (1 , 0 )},
216+                             /*  setPosixShm */ true , /*  cacheSize */ 0 )
217+           .validate (),
218+       std::invalid_argument);
175219}
176220
177221TEST_F (LruMemoryTiersTest, TestInvalid2TierConfigSizesNeCacheSize) {
178-   EXPECT_THROW (createTestCacheConfig ({defaultDaxPath, defaultPmemPath},
179-                                      {std::make_tuple (0 , 1 ), std::make_tuple (0 , 1 )}),
180-                std::invalid_argument);
222+   EXPECT_THROW (
223+       createTestCacheConfig ({defaultDaxPath, defaultPmemPath},
224+                             {std::make_tuple (0 , 1 ), std::make_tuple (0 , 1 )}),
225+       std::invalid_argument);
226+ }
227+ 
228+ TEST_F (LruMemoryTiersTest, TestTieredCacheSize) {
229+   size_t  totalSizes[] = {50  * MB, 77  * MB, 100  * MB, 101  * MB + MB / 2 ,
230+                          1  * GB,  4  * GB,  8  * GB,   9  * GB};
231+   size_t  numTiers[] = {2 , 3 , 4 };
232+ 
233+   auto  getCacheSize = [&](size_t  cacheSize, size_t  tiers) {
234+     std::unique_ptr<LruAllocator> alloc;
235+     if  (tiers < 2 ) {
236+       alloc = std::unique_ptr<LruAllocator>(
237+           new  LruAllocator (createDramCacheConfig (cacheSize)));
238+     } else  {
239+       alloc = std::unique_ptr<LruAllocator>(
240+           new  LruAllocator (LruAllocator::SharedMemNew,
241+                            createTieredCacheConfig (cacheSize, tiers)));
242+     }
243+     return  alloc->getCacheMemoryStats ().cacheSize ;
244+   };
245+ 
246+   for  (auto  totalSize : totalSizes) {
247+     auto  dramCacheSize = getCacheSize (totalSize, 1 );
248+     for  (auto  n : numTiers) {
249+       auto  tieredCacheSize = getCacheSize (totalSize, n);
250+       EXPECT_GT (dramCacheSize, tieredCacheSize);
251+       EXPECT_GE (metaDataSize * n * 2 , dramCacheSize - tieredCacheSize);
252+     }
253+   }
181254}
182255
183256} //  namespace tests
0 commit comments