MergingIterator.Seek() to lazily initialize MinHeap
Summary: For the use cases that prefix filtering is enabled, initializing heaps when doing MergingIterator.Seek() might introduce non-negligible costs. This patch makes it lazily done. Test Plan: make all check Reviewers: haobo,dhruba,kailiu CC: Task ID: # Blame Rev:
This commit is contained in:
parent
37b459f0aa
commit
15b31b57df
@ -26,6 +26,7 @@ class MergingIterator : public Iterator {
|
|||||||
: comparator_(comparator),
|
: comparator_(comparator),
|
||||||
children_(n),
|
children_(n),
|
||||||
current_(nullptr),
|
current_(nullptr),
|
||||||
|
use_heap_(true),
|
||||||
direction_(kForward),
|
direction_(kForward),
|
||||||
maxHeap_(NewMaxIterHeap(comparator_)),
|
maxHeap_(NewMaxIterHeap(comparator_)),
|
||||||
minHeap_ (NewMinIterHeap(comparator_)) {
|
minHeap_ (NewMinIterHeap(comparator_)) {
|
||||||
@ -70,14 +71,38 @@ class MergingIterator : public Iterator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void Seek(const Slice& target) {
|
virtual void Seek(const Slice& target) {
|
||||||
ClearHeaps();
|
// Invalidate the heap.
|
||||||
|
use_heap_ = false;
|
||||||
|
IteratorWrapper* first_child = nullptr;
|
||||||
for (auto& child : children_) {
|
for (auto& child : children_) {
|
||||||
child.Seek(target);
|
child.Seek(target);
|
||||||
if (child.Valid()) {
|
if (child.Valid()) {
|
||||||
minHeap_.push(&child);
|
// This child has valid key
|
||||||
|
if (!use_heap_) {
|
||||||
|
if (first_child == nullptr) {
|
||||||
|
// It's the first child has valid key. Only put it int
|
||||||
|
// current_. Now the values in the heap should be invalid.
|
||||||
|
first_child = &child;
|
||||||
|
} else {
|
||||||
|
// We have more than one children with valid keys. Initialize
|
||||||
|
// the heap and put the first child into the heap.
|
||||||
|
ClearHeaps();
|
||||||
|
minHeap_.push(first_child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (use_heap_) {
|
||||||
|
minHeap_.push(&child);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FindSmallest();
|
if (use_heap_) {
|
||||||
|
// If heap is valid, need to put the smallest key to curent_.
|
||||||
|
FindSmallest();
|
||||||
|
} else {
|
||||||
|
// The heap is not valid, then the current_ iterator is the first
|
||||||
|
// one, or null if there is no first child.
|
||||||
|
current_ = first_child;
|
||||||
|
}
|
||||||
direction_ = kForward;
|
direction_ = kForward;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,10 +134,14 @@ class MergingIterator : public Iterator {
|
|||||||
// as the current points to the current record. move the iterator forward.
|
// as the current points to the current record. move the iterator forward.
|
||||||
// and if it is valid add it to the heap.
|
// and if it is valid add it to the heap.
|
||||||
current_->Next();
|
current_->Next();
|
||||||
if (current_->Valid()){
|
if (use_heap_) {
|
||||||
minHeap_.push(current_);
|
if (current_->Valid()) {
|
||||||
|
minHeap_.push(current_);
|
||||||
|
}
|
||||||
|
FindSmallest();
|
||||||
|
} else if (!current_->Valid()) {
|
||||||
|
current_ = nullptr;
|
||||||
}
|
}
|
||||||
FindSmallest();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Prev() {
|
virtual void Prev() {
|
||||||
@ -178,6 +207,10 @@ class MergingIterator : public Iterator {
|
|||||||
const Comparator* comparator_;
|
const Comparator* comparator_;
|
||||||
std::vector<IteratorWrapper> children_;
|
std::vector<IteratorWrapper> children_;
|
||||||
IteratorWrapper* current_;
|
IteratorWrapper* 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
|
||||||
|
// valid rows.
|
||||||
|
bool use_heap_;
|
||||||
// Which direction is the iterator moving?
|
// Which direction is the iterator moving?
|
||||||
enum Direction {
|
enum Direction {
|
||||||
kForward,
|
kForward,
|
||||||
@ -189,6 +222,7 @@ class MergingIterator : public Iterator {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void MergingIterator::FindSmallest() {
|
void MergingIterator::FindSmallest() {
|
||||||
|
assert(use_heap_);
|
||||||
if (minHeap_.empty()) {
|
if (minHeap_.empty()) {
|
||||||
current_ = nullptr;
|
current_ = nullptr;
|
||||||
} else {
|
} else {
|
||||||
@ -199,6 +233,7 @@ void MergingIterator::FindSmallest() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MergingIterator::FindLargest() {
|
void MergingIterator::FindLargest() {
|
||||||
|
assert(use_heap_);
|
||||||
if (maxHeap_.empty()) {
|
if (maxHeap_.empty()) {
|
||||||
current_ = nullptr;
|
current_ = nullptr;
|
||||||
} else {
|
} else {
|
||||||
@ -209,6 +244,7 @@ void MergingIterator::FindLargest() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MergingIterator::ClearHeaps() {
|
void MergingIterator::ClearHeaps() {
|
||||||
|
use_heap_ = true;
|
||||||
maxHeap_ = NewMaxIterHeap(comparator_);
|
maxHeap_ = NewMaxIterHeap(comparator_);
|
||||||
minHeap_ = NewMinIterHeap(comparator_);
|
minHeap_ = NewMinIterHeap(comparator_);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user