-
Notifications
You must be signed in to change notification settings - Fork 277
Enable the CacheLibWrapper class as a RocksDB Plugin #184
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
00c775a
fea3f81
6130377
8392fb2
7f3b1a1
ec1186f
143ac0d
d825c15
75a540c
28a8ae3
52e2d8e
7e62abf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
cmake_minimum_required(VERSION 3.4) | ||
|
||
find_package(cachelib REQUIRED) | ||
|
||
# Suppresses errors from folly exceptions | ||
set(cachelib_SOURCES CachelibWrapper.cpp PARENT_SCOPE) | ||
set(cachelib_INCLUDE_PATHS ${CACHELIB_INCLUDE_DIR}/.. PARENT_SCOPE) | ||
set(cachelib_COMPILE_FLAGS -Wno-error=class-memaccess -Wno-error=sign-compare -Wno-error=deprecated-declarationsPARENT_SCOPE) | ||
#set(cachelib_LIBS "cachelib_allocator" "cachelib_shm" "cachelib_navy" "cachelib_common" "thriftcpp2" "thriftfrozen2" "thriftmetadata" "thriftanyrep" "thrifttype" "thrifttyperep" "thriftannotation" "thriftprotocol" "async" "wangle" "fizz" "sodium" "rt" PARENT_SCOPE) | ||
set(cachelib_LIBS "cachelib_allocator" "cachelib_shm" "cachelib_navy" "cachelib_common" "thriftcpp2" "thriftfrozen2" "thriftmetadata" "thriftanyrep" "thrifttype" "thrifttyperep" "thriftannotation" "thriftprotocol" "async" "wangle" "fizz" "folly" "folly_test_util" "fmtd" "glogd" "sodium" "boost_context" "rt" PARENT_SCOPE) | ||
set(cachelib_FUNC register_CachelibObjects PARENT_SCOPE) | ||
set(cachelib_LINK_PATHS ${CMAKE_PREFIX_PATH}/lib PARENT_SCOPE) | ||
set(cachelib_TESTS tests/CachelibWrapperTest.cpp PARENT_SCOPE) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,18 +14,19 @@ | |
* limitations under the License. | ||
*/ | ||
|
||
#include "cachelib/adaptor/rocks_secondary_cache/CachelibWrapper.h" | ||
#include "CachelibWrapper.h" | ||
|
||
#include "cachelib/facebook/utils/FbInternalRuntimeUpdateWrapper.h" | ||
#include "folly/init/Init.h" | ||
#include "folly/synchronization/Rcu.h" | ||
#include "rocksdb/convenience.h" | ||
#include "rocksdb/version.h" | ||
#include "rocksdb/utilities/object_registry.h" | ||
#include "rocksdb/utilities/options_type.h" | ||
|
||
namespace facebook { | ||
namespace rocks_secondary_cache { | ||
|
||
#define FB_CACHE_MAX_ITEM_SIZE 4 << 20 | ||
using ApiWrapper = cachelib::FbInternalRuntimeUpdateWrapper<FbCache>; | ||
|
||
namespace { | ||
// We use a separate RCU domain since read side critical sections can block | ||
|
@@ -129,8 +130,68 @@ class RocksCachelibWrapperHandle : public rocksdb::SecondaryCacheResultHandle { | |
} | ||
} | ||
}; | ||
|
||
static std::unordered_map<std::string, ROCKSDB_NAMESPACE::OptionTypeInfo> | ||
rocks_cachelib_type_info = { | ||
#ifndef ROCKSDB_LITE | ||
{"cachename", {offsetof(struct RocksCachelibOptions, cacheName), ROCKSDB_NAMESPACE::OptionType::kString}}, | ||
{"filename", {offsetof(struct RocksCachelibOptions, fileName), ROCKSDB_NAMESPACE::OptionType::kString}}, | ||
{"size", {offsetof(struct RocksCachelibOptions, size), ROCKSDB_NAMESPACE::OptionType::kSizeT}}, | ||
{"block_size", {offsetof(struct RocksCachelibOptions, blockSize), ROCKSDB_NAMESPACE::OptionType::kSizeT}}, | ||
{"region_size",{offsetof(struct RocksCachelibOptions, regionSize), ROCKSDB_NAMESPACE::OptionType::kSizeT}}, | ||
{"policy", {offsetof(struct RocksCachelibOptions, admPolicy), ROCKSDB_NAMESPACE::OptionType::kString}}, | ||
{"probability",{offsetof(struct RocksCachelibOptions, admProbability), ROCKSDB_NAMESPACE::OptionType::kDouble}}, | ||
{"max_write_rate",{offsetof(struct RocksCachelibOptions, maxWriteRate), ROCKSDB_NAMESPACE::OptionType::kUInt64T}}, | ||
{"admission_write_rate",{offsetof(struct RocksCachelibOptions, admissionWriteRate), ROCKSDB_NAMESPACE::OptionType::kUInt64T}}, | ||
{"volatile_size",{offsetof(struct RocksCachelibOptions, volatileSize), ROCKSDB_NAMESPACE::OptionType::kSizeT}}, | ||
{"bucket_power", {offsetof(struct RocksCachelibOptions, bktPower), ROCKSDB_NAMESPACE::OptionType::kUInt32T}}, | ||
{"lock_power", {offsetof(struct RocksCachelibOptions, lockPower), ROCKSDB_NAMESPACE::OptionType::kUInt32T}}, | ||
#endif // ROCKSDB_LITE | ||
}; | ||
} // namespace | ||
|
||
RocksCachelibWrapper::RocksCachelibWrapper(const RocksCachelibOptions& options) | ||
: options_(options), cache_(nullptr) { | ||
RegisterOptions(&options_, &rocks_cachelib_type_info); | ||
} | ||
|
||
ROCKSDB_NAMESPACE::Status RocksCachelibWrapper::PrepareOptions(const ROCKSDB_NAMESPACE::ConfigOptions& opts) { | ||
FbCache* cache = cache_.load(); | ||
|
||
if (!cache) { | ||
cachelib::PoolId defaultPool; | ||
FbCacheConfig config; | ||
NvmCacheConfig nvmConfig; | ||
|
||
nvmConfig.navyConfig.setBlockSize(options_.blockSize); | ||
nvmConfig.navyConfig.setSimpleFile(options_.fileName, | ||
options_.size, | ||
/*truncateFile=*/true); | ||
nvmConfig.navyConfig.blockCache().setRegionSize(options_.regionSize); | ||
if (options_.admPolicy == "random") { | ||
nvmConfig.navyConfig.enableRandomAdmPolicy().setAdmProbability( | ||
options_.admProbability); | ||
} else { | ||
nvmConfig.navyConfig.enableDynamicRandomAdmPolicy() | ||
.setMaxWriteRate(options_.maxWriteRate) | ||
.setAdmWriteRate(options_.admissionWriteRate); | ||
} | ||
nvmConfig.enableFastNegativeLookups = true; | ||
|
||
config.setCacheSize(options_.volatileSize) | ||
.setCacheName(options_.cacheName) | ||
.setAccessConfig( | ||
{options_.bktPower /* bucket power */, options_.lockPower /* lock power */}) | ||
.enableNvmCache(nvmConfig) | ||
.validate(); // will throw if bad config | ||
auto new_cache = std::make_unique<FbCache>(config); | ||
pool_ = | ||
new_cache->addPool("default", new_cache->getCacheMemoryStats().cacheSize); | ||
cache_.store(new_cache.release()); | ||
} | ||
return SecondaryCache::PrepareOptions(opts); | ||
} | ||
|
||
RocksCachelibWrapper::~RocksCachelibWrapper() { Close(); } | ||
|
||
rocksdb::Status RocksCachelibWrapper::Insert( | ||
|
@@ -225,64 +286,31 @@ void RocksCachelibWrapper::Close() { | |
// sections already started to finish, and then delete the cache | ||
cache_.store(nullptr); | ||
GetRcuDomain().synchronize(); | ||
admin_.reset(); | ||
delete cache; | ||
} | ||
} | ||
|
||
bool RocksCachelibWrapper::UpdateMaxWriteRateForDynamicRandom( | ||
uint64_t maxRate) { | ||
FbCache* cache = cache_.load(); | ||
bool ret = false; | ||
if (cache) { | ||
ret = ApiWrapper::updateMaxRateForDynamicRandomAP(*cache, maxRate); | ||
} | ||
return ret; | ||
} | ||
|
||
// Global cache object and a default cache pool | ||
std::unique_ptr<rocksdb::SecondaryCache> NewRocksCachelibWrapper( | ||
const RocksCachelibOptions& opts) { | ||
std::unique_ptr<FbCache> cache; | ||
std::unique_ptr<cachelib::CacheAdmin> admin; | ||
cachelib::PoolId defaultPool; | ||
FbCacheConfig config; | ||
NvmCacheConfig nvmConfig; | ||
|
||
nvmConfig.navyConfig.setBlockSize(opts.blockSize); | ||
nvmConfig.navyConfig.setSimpleFile(opts.fileName, | ||
opts.size, | ||
/*truncateFile=*/true); | ||
nvmConfig.navyConfig.blockCache().setRegionSize(opts.regionSize); | ||
if (opts.admPolicy == "random") { | ||
nvmConfig.navyConfig.enableRandomAdmPolicy().setAdmProbability( | ||
opts.admProbability); | ||
} else { | ||
nvmConfig.navyConfig.enableDynamicRandomAdmPolicy() | ||
.setMaxWriteRate(opts.maxWriteRate) | ||
.setAdmWriteRate(opts.admissionWriteRate); | ||
} | ||
nvmConfig.enableFastNegativeLookups = true; | ||
|
||
config.setCacheSize(opts.volatileSize) | ||
.setCacheName(opts.cacheName) | ||
.setAccessConfig( | ||
{opts.bktPower /* bucket power */, opts.lockPower /* lock power */}) | ||
.enableNvmCache(nvmConfig) | ||
.validate(); // will throw if bad config | ||
cache = std::make_unique<FbCache>(config); | ||
defaultPool = | ||
cache->addPool("default", cache->getCacheMemoryStats().cacheSize); | ||
|
||
if (opts.fb303Stats) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is CacheAdmin for stats not supported? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @anand1976 This is another piece that is internal to Facebook/Meta and is not in the public API. |
||
cachelib::CacheAdmin::Config adminConfig; | ||
adminConfig.oncall = opts.oncallName; | ||
admin = std::make_unique<cachelib::CacheAdmin>(*cache, adminConfig); | ||
} | ||
|
||
return std::unique_ptr<rocksdb::SecondaryCache>(new RocksCachelibWrapper( | ||
std::move(cache), std::move(admin), std::move(defaultPool))); | ||
std::unique_ptr<rocksdb::SecondaryCache> secondary = std::make_unique<RocksCachelibWrapper>(opts); | ||
assert(secondary->PrepareOptions(ROCKSDB_NAMESPACE::ConfigOptions()).ok()); | ||
return secondary; | ||
} | ||
|
||
#ifndef ROCKSDB_LITE | ||
int register_CachelibObjects(ROCKSDB_NAMESPACE::ObjectLibrary& library, const std::string&) { | ||
library.AddFactory<ROCKSDB_NAMESPACE::SecondaryCache>(RocksCachelibWrapper::kClassName(), | ||
[](const std::string& uri, std::unique_ptr<ROCKSDB_NAMESPACE::SecondaryCache>* guard, | ||
std::string* /*errmsg*/) { | ||
RocksCachelibOptions options; | ||
guard->reset(new RocksCachelibWrapper(options)); | ||
return guard->get(); | ||
}); | ||
return 1; | ||
} | ||
#endif // ROCKSDB_LITE | ||
} // namespace rocks_secondary_cache | ||
} // namespace facebook | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# RocksDB CacheLib Secondary Cache | ||
|
||
This directory contains files and tests for building Cachelib as a SecondaryCache for RocksDB. | ||
|
||
# Build | ||
|
||
Currently the build is only supported via cmake. | ||
|
||
First, build cachelib through the normal build procedure. | ||
|
||
To build under RocksDB, link this directory adaptor/rocksdb_secondary_cache) to the plugins/cachelib directory under RocksDB: | ||
``` | ||
$ln -s .../secondary_cache .../plugins/cachelib | ||
``` | ||
This will allow RocksDB to find and build the CacheLib plugin code. | ||
|
||
Next, under the RocksDB build directory, instruct RocksDB to build and include the cachelib plugin: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm curious, how is the folly dependency handled? Should the user do this first - https://github.com/facebook/rocksdb/wiki/RocksDB-Contribution-Guide#build-rocksdb-with-folly-integration-enabled? |
||
``` | ||
$cmake -DROCKSDB_PLUGINS=cachelib -DCMAKE_PREFIX_PATH=<Path to CacheLib> -DCMAKE_MODULE_PATH="<Path to CacheLib>" .. | ||
``` | ||
where the prefix path points to the opt/cachelib directory and module path points to the cachelib/cmake directory. | ||
|
||
Finally, build RocksDB using "make". | ||
|
||
# Using the RocksDB Cachelib Secondary Cache | ||
|
||
The Secondary Cache can be created via either the SecondaryCache::CreateFromString or NewRocksCachelibWrapper APIs. | ||
``` | ||
SecondaryCache::CreateFromString(..., "id=RocksCachelibWrapper; ..."); | ||
|
||
RoksCachelibOptions options; | ||
NewRocksCachelibWrapper(options); | ||
``` | ||
|
||
When using CreateFromString API, the options can be specified as name-value pairs on the command line. The mapping between the field names and options is found in CacheLibWrapper.cpp. | ||
|
||
# Issues and TODO | ||
|
||
* There are incompatibilities between RocksDB and Cachelib on the version of GTEST required and supported. In order to successfully build, you must use the GTEST version in Cachelib and remove the gtest from the RocksDB build. This requirement is true whether or not you are building tests. In the RocksDB build, you must remove GTEST from the "include_directories" and "add_subdirectories" and add " -Wno-error=deprecated-declarations" to the CMAKE_CXX_FLAGS. You may also need to add "-Wno-error=sign-compare" to build the RocksDB tests, depending on your compiler. | ||
|
||
* RocksDB does not currently enable plugins to build their own tests (see PR11052). When the CachelibWrapperTest is added, additional link libraries may be required (See the CMakeLists.txt file). No investigation as to the reason has been undertaken. | ||
|
||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this not be supported anymore? Internally, we need this API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@anand1976 This is a feature that is internal to Facebook/Meta. The header file that is required for this is not part of the public API.