Summary: Implement the ```WaitAll()``` interface in ```LRUCache``` to allow callers to issue multiple lookups in parallel and wait for all of them to complete. Modify ```MultiGet``` to use this to parallelize the secondary cache lookups in order to reduce the overall latency. A call to ```cache->Lookup()``` returns a handle that has an incomplete value (nullptr), and the caller can call ```cache->IsReady()``` to check whether the lookup is complete, and pass a vector of handles to ```WaitAll``` to wait for completion. If any of the lookups fail, ```MultiGet``` will read the block from the SST file. Another change in this PR is to rename ```SecondaryCacheHandle``` to ```SecondaryCacheResultHandle``` as it more accurately describes the return result of the secondary cache lookup, which is more like a future. Tests: 1. Add unit tests in lru_cache_test 2. Benchmark results with no secondary cache configured Master - ``` readrandom : 41.175 micros/op 388562 ops/sec; 106.7 MB/s (7277999 of 7277999 found) readrandom : 41.217 micros/op 388160 ops/sec; 106.6 MB/s (7274999 of 7274999 found) multireadrandom : 10.309 micros/op 1552082 ops/sec; (28908992 of 28908992 found) multireadrandom : 10.321 micros/op 1550218 ops/sec; (29081984 of 29081984 found) ``` This PR - ``` readrandom : 41.158 micros/op 388723 ops/sec; 106.8 MB/s (7290999 of 7290999 found) readrandom : 41.185 micros/op 388463 ops/sec; 106.7 MB/s (7287999 of 7287999 found) multireadrandom : 10.277 micros/op 1556801 ops/sec; (29346944 of 29346944 found) multireadrandom : 10.253 micros/op 1560539 ops/sec; (29274944 of 29274944 found) ``` Pull Request resolved: https://github.com/facebook/rocksdb/pull/8405 Reviewed By: zhichao-cao Differential Revision: D29190509 Pulled By: anand1976 fbshipit-source-id: 6f8eff6246712af8a297cfe22ea0d1c3b2a01bb0
104 lines
3.4 KiB
C++
104 lines
3.4 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).
|
|
//
|
|
|
|
#include "table/block_based/filter_block_reader_common.h"
|
|
#include "monitoring/perf_context_imp.h"
|
|
#include "table/block_based/block_based_table_reader.h"
|
|
#include "table/block_based/parsed_full_filter_block.h"
|
|
|
|
namespace ROCKSDB_NAMESPACE {
|
|
|
|
template <typename TBlocklike>
|
|
Status FilterBlockReaderCommon<TBlocklike>::ReadFilterBlock(
|
|
const BlockBasedTable* table, FilePrefetchBuffer* prefetch_buffer,
|
|
const ReadOptions& read_options, bool use_cache, GetContext* get_context,
|
|
BlockCacheLookupContext* lookup_context,
|
|
CachableEntry<TBlocklike>* filter_block) {
|
|
PERF_TIMER_GUARD(read_filter_block_nanos);
|
|
|
|
assert(table);
|
|
assert(filter_block);
|
|
assert(filter_block->IsEmpty());
|
|
|
|
const BlockBasedTable::Rep* const rep = table->get_rep();
|
|
assert(rep);
|
|
|
|
const Status s =
|
|
table->RetrieveBlock(prefetch_buffer, read_options, rep->filter_handle,
|
|
UncompressionDict::GetEmptyDict(), filter_block,
|
|
BlockType::kFilter, get_context, lookup_context,
|
|
/* for_compaction */ false, use_cache,
|
|
/* wait_for_cache */ true);
|
|
|
|
return s;
|
|
}
|
|
|
|
template <typename TBlocklike>
|
|
const SliceTransform*
|
|
FilterBlockReaderCommon<TBlocklike>::table_prefix_extractor() const {
|
|
assert(table_);
|
|
|
|
const BlockBasedTable::Rep* const rep = table_->get_rep();
|
|
assert(rep);
|
|
|
|
return rep->prefix_filtering ? rep->table_prefix_extractor.get() : nullptr;
|
|
}
|
|
|
|
template <typename TBlocklike>
|
|
bool FilterBlockReaderCommon<TBlocklike>::whole_key_filtering() const {
|
|
assert(table_);
|
|
assert(table_->get_rep());
|
|
|
|
return table_->get_rep()->whole_key_filtering;
|
|
}
|
|
|
|
template <typename TBlocklike>
|
|
bool FilterBlockReaderCommon<TBlocklike>::cache_filter_blocks() const {
|
|
assert(table_);
|
|
assert(table_->get_rep());
|
|
|
|
return table_->get_rep()->table_options.cache_index_and_filter_blocks;
|
|
}
|
|
|
|
template <typename TBlocklike>
|
|
Status FilterBlockReaderCommon<TBlocklike>::GetOrReadFilterBlock(
|
|
bool no_io, GetContext* get_context,
|
|
BlockCacheLookupContext* lookup_context,
|
|
CachableEntry<TBlocklike>* filter_block) const {
|
|
assert(filter_block);
|
|
|
|
if (!filter_block_.IsEmpty()) {
|
|
filter_block->SetUnownedValue(filter_block_.GetValue());
|
|
return Status::OK();
|
|
}
|
|
|
|
ReadOptions read_options;
|
|
if (no_io) {
|
|
read_options.read_tier = kBlockCacheTier;
|
|
}
|
|
|
|
return ReadFilterBlock(table_, nullptr /* prefetch_buffer */, read_options,
|
|
cache_filter_blocks(), get_context, lookup_context,
|
|
filter_block);
|
|
}
|
|
|
|
template <typename TBlocklike>
|
|
size_t FilterBlockReaderCommon<TBlocklike>::ApproximateFilterBlockMemoryUsage()
|
|
const {
|
|
assert(!filter_block_.GetOwnValue() || filter_block_.GetValue() != nullptr);
|
|
return filter_block_.GetOwnValue()
|
|
? filter_block_.GetValue()->ApproximateMemoryUsage()
|
|
: 0;
|
|
}
|
|
|
|
// Explicitly instantiate templates for both "blocklike" types we use.
|
|
// This makes it possible to keep the template definitions in the .cc file.
|
|
template class FilterBlockReaderCommon<BlockContents>;
|
|
template class FilterBlockReaderCommon<Block>;
|
|
template class FilterBlockReaderCommon<ParsedFullFilterBlock>;
|
|
|
|
} // namespace ROCKSDB_NAMESPACE
|