rocksdb/utilities/fault_injection_secondary_cache.cc
gitbw95 f241d082b6 Prevent double caching in the compressed secondary cache (#9747)
Summary:
###  **Summary:**
When both LRU Cache and CompressedSecondaryCache are configured together, there possibly are some data blocks double cached.

**Changes include:**
1. Update IS_PROMOTED to IS_IN_SECONDARY_CACHE to prevent confusions.
2. This PR updates SecondaryCacheResultHandle and use IsErasedFromSecondaryCache to determine whether the handle is erased in the secondary cache. Then, the caller can determine whether to SetIsInSecondaryCache().
3. Rename LRUSecondaryCache to CompressedSecondaryCache.

Pull Request resolved: https://github.com/facebook/rocksdb/pull/9747

Test Plan:
**Test Scripts:**
1. Populate a DB. The on disk footprint is 482 MB. The data is set to be 50% compressible, so the total decompressed size is expected to be 964 MB.
./db_bench --benchmarks=fillrandom --num=10000000 -db=/db_bench_1

2. overwrite it to a stable state:
./db_bench --benchmarks=overwrite,stats --num=10000000 -use_existing_db -duration=10 --benchmark_write_rate_limit=2000000 -db=/db_bench_1

4. Run read tests with diffeernt cache setting:

T1:
./db_bench --benchmarks=seekrandom,stats --threads=16 --num=10000000 -use_existing_db -duration=120 --benchmark_write_rate_limit=52000000 -use_direct_reads --cache_size=520000000  --statistics -db=/db_bench_1

T2:
./db_bench --benchmarks=seekrandom,stats --threads=16 --num=10000000 -use_existing_db -duration=120 --benchmark_write_rate_limit=52000000 -use_direct_reads --cache_size=320000000 -compressed_secondary_cache_size=400000000 --statistics -use_compressed_secondary_cache -db=/db_bench_1

T3:
./db_bench --benchmarks=seekrandom,stats --threads=16 --num=10000000 -use_existing_db -duration=120 --benchmark_write_rate_limit=52000000 -use_direct_reads --cache_size=520000000 -compressed_secondary_cache_size=400000000 --statistics -use_compressed_secondary_cache -db=/db_bench_1

T4:
./db_bench --benchmarks=seekrandom,stats --threads=16 --num=10000000 -use_existing_db -duration=120 --benchmark_write_rate_limit=52000000 -use_direct_reads --cache_size=20000000 -compressed_secondary_cache_size=500000000 --statistics -use_compressed_secondary_cache -db=/db_bench_1

**Before this PR**
| Cache Size | Compressed Secondary Cache Size | Cache Hit Rate |
|------------|-------------------------------------|----------------|
|520 MB | 0 MB | 85.5% |
|320 MB | 400 MB | 96.2% |
|520 MB | 400 MB | 98.3% |
|20 MB | 500 MB | 98.8% |

**Before this PR**
| Cache Size | Compressed Secondary Cache Size | Cache Hit Rate |
|------------|-------------------------------------|----------------|
|520 MB | 0 MB | 85.5% |
|320 MB | 400 MB | 99.9% |
|520 MB | 400 MB | 99.9% |
|20 MB | 500 MB | 99.2% |

Reviewed By: anand1976

Differential Revision: D35117499

Pulled By: gitbw95

fbshipit-source-id: ea2657749fc13efebe91a8a1b56bc61d6a224a12
2022-04-11 13:28:33 -07:00

111 lines
3.5 KiB
C++

// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
// This class implements a custom SecondaryCache that randomly injects an
// error status into Inserts/Lookups based on a specified probability.
#include "utilities/fault_injection_secondary_cache.h"
namespace ROCKSDB_NAMESPACE {
void FaultInjectionSecondaryCache::ResultHandle::UpdateHandleValue(
FaultInjectionSecondaryCache::ResultHandle* handle) {
ErrorContext* ctx = handle->cache_->GetErrorContext();
if (!ctx->rand.OneIn(handle->cache_->prob_)) {
handle->value_ = handle->base_->Value();
handle->size_ = handle->base_->Size();
}
handle->base_.reset();
}
bool FaultInjectionSecondaryCache::ResultHandle::IsReady() {
bool ready = true;
if (base_) {
ready = base_->IsReady();
if (ready) {
UpdateHandleValue(this);
}
}
return ready;
}
void FaultInjectionSecondaryCache::ResultHandle::Wait() {
base_->Wait();
UpdateHandleValue(this);
}
void* FaultInjectionSecondaryCache::ResultHandle::Value() { return value_; }
size_t FaultInjectionSecondaryCache::ResultHandle::Size() { return size_; }
void FaultInjectionSecondaryCache::ResultHandle::WaitAll(
FaultInjectionSecondaryCache* cache,
std::vector<SecondaryCacheResultHandle*> handles) {
std::vector<SecondaryCacheResultHandle*> base_handles;
for (SecondaryCacheResultHandle* hdl : handles) {
FaultInjectionSecondaryCache::ResultHandle* handle =
static_cast<FaultInjectionSecondaryCache::ResultHandle*>(hdl);
if (!handle->base_) {
continue;
}
base_handles.emplace_back(handle->base_.get());
}
cache->base_->WaitAll(base_handles);
for (SecondaryCacheResultHandle* hdl : handles) {
FaultInjectionSecondaryCache::ResultHandle* handle =
static_cast<FaultInjectionSecondaryCache::ResultHandle*>(hdl);
if (handle->base_) {
UpdateHandleValue(handle);
}
}
}
FaultInjectionSecondaryCache::ErrorContext*
FaultInjectionSecondaryCache::GetErrorContext() {
ErrorContext* ctx = static_cast<ErrorContext*>(thread_local_error_->Get());
if (!ctx) {
ctx = new ErrorContext(seed_);
thread_local_error_->Reset(ctx);
}
return ctx;
}
Status FaultInjectionSecondaryCache::Insert(
const Slice& key, void* value, const Cache::CacheItemHelper* helper) {
ErrorContext* ctx = GetErrorContext();
if (ctx->rand.OneIn(prob_)) {
return Status::IOError();
}
return base_->Insert(key, value, helper);
}
std::unique_ptr<SecondaryCacheResultHandle>
FaultInjectionSecondaryCache::Lookup(const Slice& key,
const Cache::CreateCallback& create_cb,
bool wait, bool& is_in_sec_cache) {
std::unique_ptr<SecondaryCacheResultHandle> hdl =
base_->Lookup(key, create_cb, wait, is_in_sec_cache);
ErrorContext* ctx = GetErrorContext();
if (wait && ctx->rand.OneIn(prob_)) {
hdl.reset();
}
return std::unique_ptr<FaultInjectionSecondaryCache::ResultHandle>(
new FaultInjectionSecondaryCache::ResultHandle(this, std::move(hdl)));
}
void FaultInjectionSecondaryCache::Erase(const Slice& key) {
base_->Erase(key);
}
void FaultInjectionSecondaryCache::WaitAll(
std::vector<SecondaryCacheResultHandle*> handles) {
FaultInjectionSecondaryCache::ResultHandle::WaitAll(this, handles);
}
} // namespace ROCKSDB_NAMESPACE