|  | 
|  | 1 | +/* | 
|  | 2 | + * Copyright (c) Facebook, Inc. and its affiliates. | 
|  | 3 | + * | 
|  | 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 5 | + * you may not use this file except in compliance with the License. | 
|  | 6 | + * You may obtain a copy of the License at | 
|  | 7 | + * | 
|  | 8 | + *     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 9 | + * | 
|  | 10 | + * Unless required by applicable law or agreed to in writing, software | 
|  | 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 13 | + * See the License for the specific language governing permissions and | 
|  | 14 | + * limitations under the License. | 
|  | 15 | + */ | 
|  | 16 | + | 
|  | 17 | +#include "cachelib/allocator/CacheAllocator.h" | 
|  | 18 | +#include "cachelib/allocator/MemoryTierCacheConfig.h" | 
|  | 19 | +#include "folly/init/Init.h" | 
|  | 20 | + | 
|  | 21 | +namespace facebook { | 
|  | 22 | +namespace cachelib_examples { | 
|  | 23 | +using Cache = cachelib::LruAllocator; // or Lru2QAllocator, or TinyLFUAllocator | 
|  | 24 | +using CacheConfig = typename Cache::Config; | 
|  | 25 | +using CacheKey = typename Cache::Key; | 
|  | 26 | +using CacheItemHandle = typename Cache::ItemHandle; | 
|  | 27 | +using MemoryTierCacheConfig = typename cachelib::MemoryTierCacheConfig; | 
|  | 28 | + | 
|  | 29 | +// Global cache object and a default cache pool | 
|  | 30 | +std::unique_ptr<Cache> gCache_; | 
|  | 31 | +cachelib::PoolId defaultPool_; | 
|  | 32 | + | 
|  | 33 | +void initializeCache() { | 
|  | 34 | +  CacheConfig config; | 
|  | 35 | +  config | 
|  | 36 | +      .setCacheSize(48 * 1024 * 1024) // 48 MB | 
|  | 37 | +      .setCacheName("MultiTier Cache") | 
|  | 38 | +      .enableCachePersistence("/tmp") | 
|  | 39 | +      .setAccessConfig( | 
|  | 40 | +          {25 /* bucket power */, 10 /* lock power */}) // assuming caching 20 | 
|  | 41 | +                                                        // million items | 
|  | 42 | +      .configureMemoryTiers({ | 
|  | 43 | +		      MemoryTierCacheConfig::fromShm().setRatio(1), | 
|  | 44 | +		      MemoryTierCacheConfig::fromFile("/tmp/file1").setRatio(2)}) | 
|  | 45 | +      .validate(); // will throw if bad config | 
|  | 46 | +  gCache_ = std::make_unique<Cache>(Cache::SharedMemNew, config); | 
|  | 47 | +  defaultPool_ = | 
|  | 48 | +      gCache_->addPool("default", gCache_->getCacheMemoryStats().cacheSize); | 
|  | 49 | +} | 
|  | 50 | + | 
|  | 51 | +void destroyCache() { gCache_.reset(); } | 
|  | 52 | + | 
|  | 53 | +CacheItemHandle get(CacheKey key) { return gCache_->find(key); } | 
|  | 54 | + | 
|  | 55 | +bool put(CacheKey key, const std::string& value) { | 
|  | 56 | +  auto handle = gCache_->allocate(defaultPool_, key, value.size()); | 
|  | 57 | +  if (!handle) { | 
|  | 58 | +    return false; // cache may fail to evict due to too many pending writes | 
|  | 59 | +  } | 
|  | 60 | +  std::memcpy(handle->getWritableMemory(), value.data(), value.size()); | 
|  | 61 | +  gCache_->insertOrReplace(handle); | 
|  | 62 | +  return true; | 
|  | 63 | +} | 
|  | 64 | +} // namespace cachelib_examples | 
|  | 65 | +} // namespace facebook | 
|  | 66 | + | 
|  | 67 | +using namespace facebook::cachelib_examples; | 
|  | 68 | + | 
|  | 69 | +int main(int argc, char** argv) { | 
|  | 70 | +  folly::init(&argc, &argv); | 
|  | 71 | + | 
|  | 72 | +  initializeCache(); | 
|  | 73 | + | 
|  | 74 | +  std::string value(4*1024, 'X'); // 4 KB value | 
|  | 75 | +  const size_t NUM_ITEMS = 13000; | 
|  | 76 | + | 
|  | 77 | +  // Use cache | 
|  | 78 | +  { | 
|  | 79 | +    for(size_t i = 0; i < NUM_ITEMS; ++i) { | 
|  | 80 | +	std::string key = "key" + std::to_string(i); | 
|  | 81 | +    	auto res = put(key, value); | 
|  | 82 | + | 
|  | 83 | +        std::ignore = res; | 
|  | 84 | +        assert(res); | 
|  | 85 | +    } | 
|  | 86 | + | 
|  | 87 | +    size_t nFound = 0; | 
|  | 88 | +    size_t nNotFound = 0; | 
|  | 89 | +    for(size_t i = 0; i < NUM_ITEMS; ++i) { | 
|  | 90 | +        std::string key = "key" + std::to_string(i); | 
|  | 91 | +        auto item = get(key); | 
|  | 92 | +        if(item) { | 
|  | 93 | +            ++nFound; | 
|  | 94 | +            folly::StringPiece sp{reinterpret_cast<const char*>(item->getMemory()), | 
|  | 95 | +                                  item->getSize()}; | 
|  | 96 | +            std::ignore = sp; | 
|  | 97 | +            assert(sp == value); | 
|  | 98 | +        } else { | 
|  | 99 | +            ++nNotFound; | 
|  | 100 | +	} | 
|  | 101 | +    } | 
|  | 102 | +    std::cout << "Found:\t\t" << nFound << " items\n" | 
|  | 103 | +              << "Not found:\t" << nNotFound << " items" << std::endl; | 
|  | 104 | +  } | 
|  | 105 | + | 
|  | 106 | +  destroyCache(); | 
|  | 107 | +} | 
0 commit comments