cachelib/cachebench/util/CacheConfig.h (94 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 <any>
#include "cachelib/allocator/CacheAllocator.h"
#include "cachelib/allocator/RebalanceStrategy.h"
#include "cachelib/cachebench/util/JSONConfig.h"
#include "cachelib/common/Ticker.h"
#include "cachelib/navy/common/Device.h"
namespace facebook {
namespace cachelib {
namespace cachebench {
// Monitor that is set up after CacheAllocator is created and
// destroyed before CacheAllocator is shut down.
class CacheMonitor {
public:
virtual ~CacheMonitor() = default;
};
class CacheMonitorFactory {
public:
virtual ~CacheMonitorFactory() = default;
virtual std::unique_ptr<CacheMonitor> create(LruAllocator& cache) = 0;
virtual std::unique_ptr<CacheMonitor> create(Lru2QAllocator& cache) = 0;
};
struct CacheConfig : public JSONConfig {
// by defaullt, lru allocator. can be set to LRU-2Q.
std::string allocator{"LRU"};
uint64_t cacheSizeMB{0};
uint64_t poolRebalanceIntervalSec{0};
std::string rebalanceStrategy;
uint64_t rebalanceMinSlabs{1};
double rebalanceDiffRatio{0.25};
bool moveOnSlabRelease{false};
uint64_t htBucketPower{22}; // buckets in hash table
uint64_t htLockPower{20}; // locks in hash table
// Hash table config for chained items
uint64_t chainedItemHtBucketPower{22};
uint64_t chainedItemHtLockPower{20};
// time to sleep between MMContainer reconfigures
uint64_t mmReconfigureIntervalSecs{0};
// LRU and 2Q params
uint64_t lruRefreshSec{60};
double lruRefreshRatio{0.1};
bool lruUpdateOnWrite{false};
bool lruUpdateOnRead{true};
bool tryLockUpdate{false};
// LRU param
uint64_t lruIpSpec{0};
// 2Q params
size_t lru2qHotPct{20};
size_t lru2qColdPct{20};
double allocFactor{1.5};
// maximum alloc size generated using the alloc factor above.
size_t maxAllocSize{1024 * 1024};
size_t minAllocSize{64};
std::vector<uint64_t> allocSizes{};
// These specify the number of pools and how keys will
// be distributed among the pools
uint64_t numPools{1};
std::vector<double> poolSizes{1.0};
// uses a user specified file for caching. If the path specified is a file
// or raw device, then navy uses that directly. If the path specificied is a
// directory, we will create a file inside with appropriate size . If a
// directory is specified by user, cachebench cleans it up at exit. If it is
// a file, cachebench preserves the file upon exit. User can also specify a
// number of devices. Cachelib's flash cache engine (Navy) will use them in a
// raid0 fashion
std::vector<std::string> nvmCachePaths{};
// size of the NVM for caching. When more than one device path is
// specified, this is the size per device path. When this is non-zero and
// nvmCachePaths is empty, an in-memory block device is used.
uint64_t nvmCacheSizeMB{0};
// list of device identifiers for the device path that can be used to
// monitor the physical write amplification. If empty, physical write amp is
// not computed. This can be specified as nvme1n1 or nvme1n2 etc, confirming
// to be a physical device identifier;
std::vector<std::string> writeAmpDeviceList{};
// Navy specific: block size in bytes
uint64_t navyBlockSize{512};
// Navy specific: region size in MB
uint64_t navyRegionSizeMB{16};
// If non-empty, configures Navy to use FIFO instead of LRU. If there are
// more than one values provided, it enables segmented fifo with the
// appropriate ratios.
std::vector<unsigned int> navySegmentedFifoSegmentRatio{};
// size classes for large objects in Navy that exceed the
// @navySmallItemMaxSize. Must be multiples of @navyBlockSize unless
// in-mem buffer is enabled. If empty, navy will use stack allocation mode.
std::vector<uint32_t> navySizeClasses{512, 2 * 512, 3 * 512,
4 * 512, 6 * 512, 8 * 512,
12 * 512, 16 * 512, 32 * 512};
// Number of shards expressed as power of two for request ordering in
// Navy. If 0, the default configuration of Navy(20) is used.
uint64_t navyReqOrderShardsPower{21};
// percentage of the nvm cache size that is dedicated for objects that are
// smaller than @navySmallItemMaxSize. This size is dedicated for BigHash
// engine.
uint64_t navyBigHashSizePct = 50;
// bucket size for BigHash. This controls the write amplification for small
// objects in Navy. Every small object write performs a RMW for a bucket.
uint64_t navyBigHashBucketSize = 4096;
// Big Hash bloom filter size in bytes per bucket above.
uint64_t navyBloomFilterPerBucketSize = 8;
// Small Item Max Size determines the upper bound of an item size that
// can be admitted into Big Hash engine.
uint64_t navySmallItemMaxSize = 2048;
// total memory limit for in-flight insertion operations for NVM. Once this is
// reached, requests will be rejected until the memory usage gets under
// the limit.
uint64_t navyParcelMemoryMB = 1024;
// use a hits based reinsertion policy with navy
uint64_t navyHitsReinsertionThreshold{0};
// use a probability based reinsertion policy with navy
uint64_t navyProbabilityReinsertionThreshold{0};
// number of asynchronous worker thread for navy read operation.
uint32_t navyReaderThreads{32};
// number of asynchronous worker thread for navy write operation,
uint32_t navyWriterThreads{32};
// buffer of clean regions to be maintained free to ensure writes
// into navy don't queue behind a reclaim of region.
uint32_t navyCleanRegions{1};
// disabled when value is 0
uint32_t navyAdmissionWriteRateMB{0};
// maximum pending inserts before rejecting new inserts.
uint32_t navyMaxConcurrentInserts{1000000};
// enables data checksuming for navy. metadata checksum is enabled by
// default
bool navyDataChecksum{true};
// by default, only store the size requested by the user into nvm cache
bool truncateItemToOriginalAllocSizeInNvm = false;
// by default, we do not encrypt content in Navy
bool navyEncryption = false;
// number of navy in-memory buffers
uint32_t navyNumInmemBuffers{30};
// By default Navy will only flush to device at most 1MB, if larger than 1MB,
// Navy will split it into multiple IOs.
uint32_t deviceMaxWriteSize{1024 * 1024};
// Don't write to flash if cache TTL is smaller than this value.
// Not used when its value is 0. In seconds.
uint32_t memoryOnlyTTL{0};
// If enabled, we will use nvm admission policy tuned for ML use cases
std::string mlNvmAdmissionPolicy{""};
// This must be non-empty if @mlNvmAdmissionPolicy is true. We specify
// a location for the ML model using this argument.
std::string mlNvmAdmissionPolicyLocation{""};
// The target recall of the ML model.
// TODO: use an opaque config file path and put that path location here if we
// need to expose more configs related to ML model.
double mlNvmAdmissionTargetRecall{0.9};
// If enabled, we will use the timestamps from the trace file in the ticker
// so that the cachebench will observe time based on timestamps from the trace
// instead of the system time.
bool useTraceTimeStamp{false};
// If enabled, when printing CacheStats, also print the NvmCounters (could be
// spammy).
bool printNvmCounters{false};
// When set to positive, CacheBench use this as TimeStampTickers bucket ticks
// For example, a value of 3600 means the threads will
// always be processing traces from the same hour at any time.
// When set to 0, TimeStampTicker is not used.
uint64_t tickerSynchingSeconds{0};
//
// Options below are not to be populated with JSON
//
// User is free to implement any encryption that conforms to this API
// If supplied, all payloads into Navy will be encrypted.
std::function<std::shared_ptr<navy::DeviceEncryptor>()> createEncryptor;
// User will implement a function that returns NvmAdmissionPolicy.
// The reason we return as a std::any is because the interface is a virtual
// template class, and the actual type is determined by @allocator in
// this config.
std::function<std::any(const CacheConfig&)> nvmAdmissionPolicyFactory;
// User can implement a structure that polls stats from CacheAllocator
// and saves the states to a backend/file/place they prefer.
std::shared_ptr<CacheMonitorFactory> cacheMonitorFactory;
// shared pointer of the ticker to support time stamp based cachebench
// simulation. Stressor uses this to pass the ticker into the cache.
std::shared_ptr<cachelib::Ticker> ticker;
// Check if ItemDestructor is triggered properly for every item.
// Be careful that this will keep a record of every item allocated,
// and won't be dropped after item is removed from cache, it the size
// is not bounded by the size of cache.
bool enableItemDestructorCheck{false};
// enable the ItemDestructor feature, but not check correctness,
// this verifies whether the feature affects throughputs.
bool enableItemDestructor{false};
explicit CacheConfig(const folly::dynamic& configJson);
CacheConfig() {}
std::shared_ptr<RebalanceStrategy> getRebalanceStrategy() const;
};
} // namespace cachebench
} // namespace cachelib
} // namespace facebook