Skip to content

Commit 15b31b5

Browse files
committed
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:
1 parent 37b459f commit 15b31b5

File tree

1 file changed

+42
-6
lines changed

1 file changed

+42
-6
lines changed

table/merger.cc

+42-6
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class MergingIterator : public Iterator {
2626
: comparator_(comparator),
2727
children_(n),
2828
current_(nullptr),
29+
use_heap_(true),
2930
direction_(kForward),
3031
maxHeap_(NewMaxIterHeap(comparator_)),
3132
minHeap_ (NewMinIterHeap(comparator_)) {
@@ -70,14 +71,38 @@ class MergingIterator : public Iterator {
7071
}
7172

7273
virtual void Seek(const Slice& target) {
73-
ClearHeaps();
74+
// Invalidate the heap.
75+
use_heap_ = false;
76+
IteratorWrapper* first_child = nullptr;
7477
for (auto& child : children_) {
7578
child.Seek(target);
7679
if (child.Valid()) {
77-
minHeap_.push(&child);
80+
// This child has valid key
81+
if (!use_heap_) {
82+
if (first_child == nullptr) {
83+
// It's the first child has valid key. Only put it int
84+
// current_. Now the values in the heap should be invalid.
85+
first_child = &child;
86+
} else {
87+
// We have more than one children with valid keys. Initialize
88+
// the heap and put the first child into the heap.
89+
ClearHeaps();
90+
minHeap_.push(first_child);
91+
}
92+
}
93+
if (use_heap_) {
94+
minHeap_.push(&child);
95+
}
7896
}
7997
}
80-
FindSmallest();
98+
if (use_heap_) {
99+
// If heap is valid, need to put the smallest key to curent_.
100+
FindSmallest();
101+
} else {
102+
// The heap is not valid, then the current_ iterator is the first
103+
// one, or null if there is no first child.
104+
current_ = first_child;
105+
}
81106
direction_ = kForward;
82107
}
83108

@@ -109,10 +134,14 @@ class MergingIterator : public Iterator {
109134
// as the current points to the current record. move the iterator forward.
110135
// and if it is valid add it to the heap.
111136
current_->Next();
112-
if (current_->Valid()){
113-
minHeap_.push(current_);
137+
if (use_heap_) {
138+
if (current_->Valid()) {
139+
minHeap_.push(current_);
140+
}
141+
FindSmallest();
142+
} else if (!current_->Valid()) {
143+
current_ = nullptr;
114144
}
115-
FindSmallest();
116145
}
117146

118147
virtual void Prev() {
@@ -178,6 +207,10 @@ class MergingIterator : public Iterator {
178207
const Comparator* comparator_;
179208
std::vector<IteratorWrapper> children_;
180209
IteratorWrapper* current_;
210+
// If the value is true, both of iterators in the heap and current_
211+
// contain valid rows. If it is false, only current_ can possibly contain
212+
// valid rows.
213+
bool use_heap_;
181214
// Which direction is the iterator moving?
182215
enum Direction {
183216
kForward,
@@ -189,6 +222,7 @@ class MergingIterator : public Iterator {
189222
};
190223

191224
void MergingIterator::FindSmallest() {
225+
assert(use_heap_);
192226
if (minHeap_.empty()) {
193227
current_ = nullptr;
194228
} else {
@@ -199,6 +233,7 @@ void MergingIterator::FindSmallest() {
199233
}
200234

201235
void MergingIterator::FindLargest() {
236+
assert(use_heap_);
202237
if (maxHeap_.empty()) {
203238
current_ = nullptr;
204239
} else {
@@ -209,6 +244,7 @@ void MergingIterator::FindLargest() {
209244
}
210245

211246
void MergingIterator::ClearHeaps() {
247+
use_heap_ = true;
212248
maxHeap_ = NewMaxIterHeap(comparator_);
213249
minHeap_ = NewMinIterHeap(comparator_);
214250
}

0 commit comments

Comments
 (0)