MergingIterator uses autovector instead of vector
Summary: Use autovector in MergingIterator so that if there are 4 or less child iterators in it, iterator wrappers are inline, which is more likely to be cache friendly. Based on one test run with a shadow traffic of one product, it reduces CPU of MergingIterator::Seek() by half. Test Plan: make all check Reviewers: haobo, yhchiang, igor, dhruba Reviewed By: igor CC: leveldb Differential Revision: https://reviews.facebook.net/D18531
This commit is contained in:
parent
af7453a673
commit
ddd41146c4
@ -20,6 +20,13 @@ class IteratorWrapper {
|
|||||||
explicit IteratorWrapper(Iterator* iter): iter_(nullptr) {
|
explicit IteratorWrapper(Iterator* iter): iter_(nullptr) {
|
||||||
Set(iter);
|
Set(iter);
|
||||||
}
|
}
|
||||||
|
IteratorWrapper(const IteratorWrapper&) {
|
||||||
|
// Iterator wrapper exclusively owns iter_ so it cannot be copied.
|
||||||
|
// Didn't delete the function because vector<IteratorWrapper> requires
|
||||||
|
// this function to compile.
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
void operator=(const IteratorWrapper&) = delete;
|
||||||
~IteratorWrapper() { delete iter_; }
|
~IteratorWrapper() { delete iter_; }
|
||||||
Iterator* iter() const { return iter_; }
|
Iterator* iter() const { return iter_; }
|
||||||
|
|
||||||
@ -35,7 +42,6 @@ class IteratorWrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Iterator interface methods
|
// Iterator interface methods
|
||||||
bool Valid() const { return valid_; }
|
bool Valid() const { return valid_; }
|
||||||
Slice key() const { assert(Valid()); return key_; }
|
Slice key() const { assert(Valid()); return key_; }
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "table/iterator_wrapper.h"
|
#include "table/iterator_wrapper.h"
|
||||||
#include "util/stop_watch.h"
|
#include "util/stop_watch.h"
|
||||||
#include "util/perf_context_imp.h"
|
#include "util/perf_context_imp.h"
|
||||||
|
#include "util/autovector.h"
|
||||||
|
|
||||||
namespace rocksdb {
|
namespace rocksdb {
|
||||||
namespace {
|
namespace {
|
||||||
@ -43,16 +44,18 @@ MinIterHeap NewMinIterHeap(const Comparator* comparator) {
|
|||||||
return MinIterHeap(MinIteratorComparator(comparator));
|
return MinIterHeap(MinIteratorComparator(comparator));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const size_t kNumIterReserve = 4;
|
||||||
|
|
||||||
class MergingIterator : public Iterator {
|
class MergingIterator : public Iterator {
|
||||||
public:
|
public:
|
||||||
MergingIterator(const Comparator* comparator, Iterator** children, int n)
|
MergingIterator(const Comparator* comparator, Iterator** children, int n)
|
||||||
: comparator_(comparator),
|
: comparator_(comparator),
|
||||||
children_(n),
|
|
||||||
current_(nullptr),
|
current_(nullptr),
|
||||||
use_heap_(true),
|
use_heap_(true),
|
||||||
direction_(kForward),
|
direction_(kForward),
|
||||||
maxHeap_(NewMaxIterHeap(comparator_)),
|
maxHeap_(NewMaxIterHeap(comparator_)),
|
||||||
minHeap_(NewMinIterHeap(comparator_)) {
|
minHeap_(NewMinIterHeap(comparator_)) {
|
||||||
|
children_.resize(n);
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
children_[i].Set(children[i]);
|
children_[i].Set(children[i]);
|
||||||
}
|
}
|
||||||
@ -240,7 +243,7 @@ class MergingIterator : public Iterator {
|
|||||||
void ClearHeaps();
|
void ClearHeaps();
|
||||||
|
|
||||||
const Comparator* comparator_;
|
const Comparator* comparator_;
|
||||||
std::vector<IteratorWrapper> children_;
|
autovector<IteratorWrapper, kNumIterReserve> children_;
|
||||||
IteratorWrapper* current_;
|
IteratorWrapper* current_;
|
||||||
// If the value is true, both of iterators in the heap and current_
|
// If the value is true, both of iterators in the heap and current_
|
||||||
// contain valid rows. If it is false, only current_ can possibly contain
|
// contain valid rows. If it is false, only current_ can possibly contain
|
||||||
|
Loading…
Reference in New Issue
Block a user