Make InternalKeyComparator final and directly use it in merging iterator
Summary: Merging iterator invokes InternalKeyComparator.Compare() frequently to heap merge. By making InternalKeyComparator final and merging iterator to directly use InternalKeyComparator rather than through Iterator interface, we can give compiler a choice to avoid one more virtual function call if possible. I ran readseq benchmark in memory-only use case to make sure the performance at least doesn't regress. I have to disable the final key word in debug build, as a hack test class depends on overriding the class. Closes https://github.com/facebook/rocksdb/pull/2860 Differential Revision: D5800461 Pulled By: siying fbshipit-source-id: ab876f22a09bb5c560740911412336e0e25ccb53
This commit is contained in:
parent
2dd22e5449
commit
64b6452e0c
@ -136,7 +136,11 @@ inline ValueType ExtractValueType(const Slice& internal_key) {
|
|||||||
|
|
||||||
// A comparator for internal keys that uses a specified comparator for
|
// A comparator for internal keys that uses a specified comparator for
|
||||||
// the user key portion and breaks ties by decreasing sequence number.
|
// the user key portion and breaks ties by decreasing sequence number.
|
||||||
class InternalKeyComparator : public Comparator {
|
class InternalKeyComparator
|
||||||
|
#ifdef NDEBUG
|
||||||
|
final
|
||||||
|
#endif
|
||||||
|
: public Comparator {
|
||||||
private:
|
private:
|
||||||
const Comparator* user_comparator_;
|
const Comparator* user_comparator_;
|
||||||
std::string name_;
|
std::string name_;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "rocksdb/comparator.h"
|
#include "db/dbformat.h"
|
||||||
#include "table/iterator_wrapper.h"
|
#include "table/iterator_wrapper.h"
|
||||||
|
|
||||||
namespace rocksdb {
|
namespace rocksdb {
|
||||||
@ -15,28 +15,28 @@ namespace rocksdb {
|
|||||||
// iterator with the max/largest key on top.
|
// iterator with the max/largest key on top.
|
||||||
class MaxIteratorComparator {
|
class MaxIteratorComparator {
|
||||||
public:
|
public:
|
||||||
MaxIteratorComparator(const Comparator* comparator) :
|
MaxIteratorComparator(const InternalKeyComparator* comparator)
|
||||||
comparator_(comparator) {}
|
: comparator_(comparator) {}
|
||||||
|
|
||||||
bool operator()(IteratorWrapper* a, IteratorWrapper* b) const {
|
bool operator()(IteratorWrapper* a, IteratorWrapper* b) const {
|
||||||
return comparator_->Compare(a->key(), b->key()) < 0;
|
return comparator_->Compare(a->key(), b->key()) < 0;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
const Comparator* comparator_;
|
const InternalKeyComparator* comparator_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// When used with std::priority_queue, this comparison functor puts the
|
// When used with std::priority_queue, this comparison functor puts the
|
||||||
// iterator with the min/smallest key on top.
|
// iterator with the min/smallest key on top.
|
||||||
class MinIteratorComparator {
|
class MinIteratorComparator {
|
||||||
public:
|
public:
|
||||||
MinIteratorComparator(const Comparator* comparator) :
|
MinIteratorComparator(const InternalKeyComparator* comparator)
|
||||||
comparator_(comparator) {}
|
: comparator_(comparator) {}
|
||||||
|
|
||||||
bool operator()(IteratorWrapper* a, IteratorWrapper* b) const {
|
bool operator()(IteratorWrapper* a, IteratorWrapper* b) const {
|
||||||
return comparator_->Compare(a->key(), b->key()) > 0;
|
return comparator_->Compare(a->key(), b->key()) > 0;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
const Comparator* comparator_;
|
const InternalKeyComparator* comparator_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace rocksdb
|
} // namespace rocksdb
|
||||||
|
@ -15,12 +15,18 @@ namespace rocksdb {
|
|||||||
class MergerTest : public testing::Test {
|
class MergerTest : public testing::Test {
|
||||||
public:
|
public:
|
||||||
MergerTest()
|
MergerTest()
|
||||||
: rnd_(3), merging_iterator_(nullptr), single_iterator_(nullptr) {}
|
: icomp_(BytewiseComparator()),
|
||||||
|
rnd_(3),
|
||||||
|
merging_iterator_(nullptr),
|
||||||
|
single_iterator_(nullptr) {}
|
||||||
~MergerTest() = default;
|
~MergerTest() = default;
|
||||||
std::vector<std::string> GenerateStrings(size_t len, int string_len) {
|
std::vector<std::string> GenerateStrings(size_t len, int string_len) {
|
||||||
std::vector<std::string> ret;
|
std::vector<std::string> ret;
|
||||||
|
|
||||||
for (size_t i = 0; i < len; ++i) {
|
for (size_t i = 0; i < len; ++i) {
|
||||||
ret.push_back(test::RandomHumanReadableString(&rnd_, string_len));
|
InternalKey ik(test::RandomHumanReadableString(&rnd_, string_len), 0,
|
||||||
|
ValueType::kTypeValue);
|
||||||
|
ret.push_back(ik.Encode().ToString(false));
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -37,7 +43,11 @@ class MergerTest : public testing::Test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SeekToRandom() { Seek(test::RandomHumanReadableString(&rnd_, 5)); }
|
void SeekToRandom() {
|
||||||
|
InternalKey ik(test::RandomHumanReadableString(&rnd_, 5), 0,
|
||||||
|
ValueType::kTypeValue);
|
||||||
|
Seek(ik.Encode().ToString(false));
|
||||||
|
}
|
||||||
|
|
||||||
void Seek(std::string target) {
|
void Seek(std::string target) {
|
||||||
merging_iterator_->Seek(target);
|
merging_iterator_->Seek(target);
|
||||||
@ -96,11 +106,12 @@ class MergerTest : public testing::Test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
merging_iterator_.reset(
|
merging_iterator_.reset(
|
||||||
NewMergingIterator(BytewiseComparator(), &small_iterators[0],
|
NewMergingIterator(&icomp_, &small_iterators[0],
|
||||||
static_cast<int>(small_iterators.size())));
|
static_cast<int>(small_iterators.size())));
|
||||||
single_iterator_.reset(new test::VectorIterator(all_keys_));
|
single_iterator_.reset(new test::VectorIterator(all_keys_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InternalKeyComparator icomp_;
|
||||||
Random rnd_;
|
Random rnd_;
|
||||||
std::unique_ptr<InternalIterator> merging_iterator_;
|
std::unique_ptr<InternalIterator> merging_iterator_;
|
||||||
std::unique_ptr<InternalIterator> single_iterator_;
|
std::unique_ptr<InternalIterator> single_iterator_;
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "table/merging_iterator.h"
|
#include "table/merging_iterator.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "db/dbformat.h"
|
||||||
#include "db/pinned_iterators_manager.h"
|
#include "db/pinned_iterators_manager.h"
|
||||||
#include "monitoring/perf_context_imp.h"
|
#include "monitoring/perf_context_imp.h"
|
||||||
#include "rocksdb/comparator.h"
|
#include "rocksdb/comparator.h"
|
||||||
@ -35,8 +36,9 @@ const size_t kNumIterReserve = 4;
|
|||||||
|
|
||||||
class MergingIterator : public InternalIterator {
|
class MergingIterator : public InternalIterator {
|
||||||
public:
|
public:
|
||||||
MergingIterator(const Comparator* comparator, InternalIterator** children,
|
MergingIterator(const InternalKeyComparator* comparator,
|
||||||
int n, bool is_arena_mode, bool prefix_seek_mode)
|
InternalIterator** children, int n, bool is_arena_mode,
|
||||||
|
bool prefix_seek_mode)
|
||||||
: is_arena_mode_(is_arena_mode),
|
: is_arena_mode_(is_arena_mode),
|
||||||
comparator_(comparator),
|
comparator_(comparator),
|
||||||
current_(nullptr),
|
current_(nullptr),
|
||||||
@ -307,7 +309,7 @@ class MergingIterator : public InternalIterator {
|
|||||||
void InitMaxHeap();
|
void InitMaxHeap();
|
||||||
|
|
||||||
bool is_arena_mode_;
|
bool is_arena_mode_;
|
||||||
const Comparator* comparator_;
|
const InternalKeyComparator* comparator_;
|
||||||
autovector<IteratorWrapper, kNumIterReserve> children_;
|
autovector<IteratorWrapper, kNumIterReserve> children_;
|
||||||
|
|
||||||
// Cached pointer to child iterator with the current key, or nullptr if no
|
// Cached pointer to child iterator with the current key, or nullptr if no
|
||||||
@ -353,7 +355,7 @@ void MergingIterator::InitMaxHeap() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InternalIterator* NewMergingIterator(const Comparator* cmp,
|
InternalIterator* NewMergingIterator(const InternalKeyComparator* cmp,
|
||||||
InternalIterator** list, int n,
|
InternalIterator** list, int n,
|
||||||
Arena* arena, bool prefix_seek_mode) {
|
Arena* arena, bool prefix_seek_mode) {
|
||||||
assert(n >= 0);
|
assert(n >= 0);
|
||||||
@ -371,8 +373,8 @@ InternalIterator* NewMergingIterator(const Comparator* cmp,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MergeIteratorBuilder::MergeIteratorBuilder(const Comparator* comparator,
|
MergeIteratorBuilder::MergeIteratorBuilder(
|
||||||
Arena* a, bool prefix_seek_mode)
|
const InternalKeyComparator* comparator, Arena* a, bool prefix_seek_mode)
|
||||||
: first_iter(nullptr), use_merging_iter(false), arena(a) {
|
: first_iter(nullptr), use_merging_iter(false), arena(a) {
|
||||||
auto mem = arena->AllocateAligned(sizeof(MergingIterator));
|
auto mem = arena->AllocateAligned(sizeof(MergingIterator));
|
||||||
merge_iter =
|
merge_iter =
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "db/dbformat.h"
|
||||||
#include "rocksdb/types.h"
|
#include "rocksdb/types.h"
|
||||||
|
|
||||||
namespace rocksdb {
|
namespace rocksdb {
|
||||||
@ -26,10 +27,9 @@ class Arena;
|
|||||||
// key is present in K child iterators, it will be yielded K times.
|
// key is present in K child iterators, it will be yielded K times.
|
||||||
//
|
//
|
||||||
// REQUIRES: n >= 0
|
// REQUIRES: n >= 0
|
||||||
extern InternalIterator* NewMergingIterator(const Comparator* comparator,
|
extern InternalIterator* NewMergingIterator(
|
||||||
InternalIterator** children, int n,
|
const InternalKeyComparator* comparator, InternalIterator** children, int n,
|
||||||
Arena* arena = nullptr,
|
Arena* arena = nullptr, bool prefix_seek_mode = false);
|
||||||
bool prefix_seek_mode = false);
|
|
||||||
|
|
||||||
class MergingIterator;
|
class MergingIterator;
|
||||||
|
|
||||||
@ -38,8 +38,8 @@ class MergeIteratorBuilder {
|
|||||||
public:
|
public:
|
||||||
// comparator: the comparator used in merging comparator
|
// comparator: the comparator used in merging comparator
|
||||||
// arena: where the merging iterator needs to be allocated from.
|
// arena: where the merging iterator needs to be allocated from.
|
||||||
explicit MergeIteratorBuilder(const Comparator* comparator, Arena* arena,
|
explicit MergeIteratorBuilder(const InternalKeyComparator* comparator,
|
||||||
bool prefix_seek_mode = false);
|
Arena* arena, bool prefix_seek_mode = false);
|
||||||
~MergeIteratorBuilder() {}
|
~MergeIteratorBuilder() {}
|
||||||
|
|
||||||
// Add iter to the merging iterator.
|
// Add iter to the merging iterator.
|
||||||
|
@ -72,6 +72,7 @@ class ErrorEnv : public EnvWrapper {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
// An internal comparator that just forward comparing results from the
|
// An internal comparator that just forward comparing results from the
|
||||||
// user comparator in it. Can be used to test entities that have no dependency
|
// user comparator in it. Can be used to test entities that have no dependency
|
||||||
// on internal key structure but consumes InternalKeyComparator, like
|
// on internal key structure but consumes InternalKeyComparator, like
|
||||||
@ -94,6 +95,7 @@ class PlainInternalKeyComparator : public InternalKeyComparator {
|
|||||||
user_comparator()->FindShortSuccessor(key);
|
user_comparator()->FindShortSuccessor(key);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
// A test comparator which compare two strings in this way:
|
// A test comparator which compare two strings in this way:
|
||||||
// (1) first compare prefix of 8 bytes in alphabet order,
|
// (1) first compare prefix of 8 bytes in alphabet order,
|
||||||
|
@ -32,6 +32,7 @@ DateTieredDBImpl::DateTieredDBImpl(
|
|||||||
: db_(db),
|
: db_(db),
|
||||||
cf_options_(ColumnFamilyOptions(options)),
|
cf_options_(ColumnFamilyOptions(options)),
|
||||||
ioptions_(ImmutableCFOptions(options)),
|
ioptions_(ImmutableCFOptions(options)),
|
||||||
|
icomp_(cf_options_.comparator),
|
||||||
ttl_(ttl),
|
ttl_(ttl),
|
||||||
column_family_interval_(column_family_interval),
|
column_family_interval_(column_family_interval),
|
||||||
mutex_(options.statistics.get(), db->GetEnv(), DB_MUTEX_WAIT_MICROS,
|
mutex_(options.statistics.get(), db->GetEnv(), DB_MUTEX_WAIT_MICROS,
|
||||||
@ -382,7 +383,7 @@ Iterator* DateTieredDBImpl::NewIterator(const ReadOptions& opts) {
|
|||||||
cf_options_.max_sequential_skip_in_iterations, 0);
|
cf_options_.max_sequential_skip_in_iterations, 0);
|
||||||
|
|
||||||
auto arena = db_iter->GetArena();
|
auto arena = db_iter->GetArena();
|
||||||
MergeIteratorBuilder builder(cf_options_.comparator, arena);
|
MergeIteratorBuilder builder(&icomp_, arena);
|
||||||
for (auto& item : handle_map_) {
|
for (auto& item : handle_map_) {
|
||||||
auto handle = item.second;
|
auto handle = item.second;
|
||||||
builder.AddIterator(db_impl->NewInternalIterator(
|
builder.AddIterator(db_impl->NewInternalIterator(
|
||||||
|
@ -56,6 +56,8 @@ class DateTieredDBImpl : public DateTieredDB {
|
|||||||
|
|
||||||
const ImmutableCFOptions ioptions_;
|
const ImmutableCFOptions ioptions_;
|
||||||
|
|
||||||
|
const InternalKeyComparator icomp_;
|
||||||
|
|
||||||
// Storing all column family handles for time series data.
|
// Storing all column family handles for time series data.
|
||||||
std::vector<ColumnFamilyHandle*> handles_;
|
std::vector<ColumnFamilyHandle*> handles_;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user