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:
sdong 2014-05-08 13:32:45 -07:00
parent af7453a673
commit ddd41146c4
2 changed files with 12 additions and 3 deletions

View File

@ -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_; }

View File

@ -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