use union for minHeap_ and maxHeap_

This commit is contained in:
leipeng 2021-10-14 11:58:15 +08:00
parent ab6755711b
commit 09e55c7596

View File

@ -73,6 +73,7 @@ class MergingIterator : public InternalIterator {
child.DeleteIter(is_arena_mode_); child.DeleteIter(is_arena_mode_);
} }
status_.PermitUncheckedError(); status_.PermitUncheckedError();
minHeap_.~MergerMinIterHeap();
} }
bool Valid() const override { return current_ != nullptr && status_.ok(); } bool Valid() const override { return current_ != nullptr && status_.ok(); }
@ -80,7 +81,7 @@ class MergingIterator : public InternalIterator {
Status status() const override { return status_; } Status status() const override { return status_; }
void SeekToFirst() override { void SeekToFirst() override {
ClearHeaps(); InitMinHeap();
status_ = Status::OK(); status_ = Status::OK();
for (auto& child : children_) { for (auto& child : children_) {
child.SeekToFirst(); child.SeekToFirst();
@ -91,7 +92,6 @@ class MergingIterator : public InternalIterator {
} }
void SeekToLast() override { void SeekToLast() override {
ClearHeaps();
InitMaxHeap(); InitMaxHeap();
status_ = Status::OK(); status_ = Status::OK();
for (auto& child : children_) { for (auto& child : children_) {
@ -103,7 +103,7 @@ class MergingIterator : public InternalIterator {
} }
void Seek(const Slice& target) override { void Seek(const Slice& target) override {
ClearHeaps(); InitMinHeap();
status_ = Status::OK(); status_ = Status::OK();
for (auto& child : children_) { for (auto& child : children_) {
{ {
@ -127,7 +127,6 @@ class MergingIterator : public InternalIterator {
} }
void SeekForPrev(const Slice& target) override { void SeekForPrev(const Slice& target) override {
ClearHeaps();
InitMaxHeap(); InitMaxHeap();
status_ = Status::OK(); status_ = Status::OK();
@ -216,11 +215,11 @@ class MergingIterator : public InternalIterator {
// replace_top() to restore the heap property. When the same child // replace_top() to restore the heap property. When the same child
// iterator yields a sequence of keys, this is cheap. // iterator yields a sequence of keys, this is cheap.
assert(current_->status().ok()); assert(current_->status().ok());
maxHeap_->replace_top(current_); maxHeap_.replace_top(current_);
} else { } else {
// current stopped being valid, remove it from the heap. // current stopped being valid, remove it from the heap.
considerStatus(current_->status()); considerStatus(current_->status());
maxHeap_->pop(); maxHeap_.pop();
} }
current_ = CurrentReverse(); current_ = CurrentReverse();
} }
@ -280,11 +279,8 @@ class MergingIterator : public InternalIterator {
} }
private: private:
// Clears heaps for both directions, used when changing direction or seeking
void ClearHeaps();
// Ensures that maxHeap_ is initialized when starting to go in the reverse
// direction
void InitMaxHeap(); void InitMaxHeap();
void InitMinHeap();
bool is_arena_mode_; bool is_arena_mode_;
bool prefix_seek_mode_; bool prefix_seek_mode_;
@ -300,11 +296,11 @@ class MergingIterator : public InternalIterator {
IteratorWrapper* current_; IteratorWrapper* current_;
// If any of the children have non-ok status, this is one of them. // If any of the children have non-ok status, this is one of them.
Status status_; Status status_;
union {
MergerMinIterHeap minHeap_; MergerMinIterHeap minHeap_;
MergerMaxIterHeap maxHeap_;
};
// Max heap is used for reverse iteration, which is way less common than
// forward. Lazily initialize it to save memory.
std::unique_ptr<MergerMaxIterHeap> maxHeap_;
PinnedIteratorsManager* pinned_iters_mgr_; PinnedIteratorsManager* pinned_iters_mgr_;
// In forward direction, process a child that is not in the min heap. // In forward direction, process a child that is not in the min heap.
@ -328,8 +324,7 @@ class MergingIterator : public InternalIterator {
IteratorWrapper* CurrentReverse() const { IteratorWrapper* CurrentReverse() const {
assert(direction_ == kReverse); assert(direction_ == kReverse);
assert(maxHeap_); return !maxHeap_.empty() ? maxHeap_.top() : nullptr;
return !maxHeap_->empty() ? maxHeap_->top() : nullptr;
} }
}; };
@ -345,7 +340,7 @@ void MergingIterator::AddToMinHeapOrCheckStatus(IteratorWrapper* child) {
void MergingIterator::AddToMaxHeapOrCheckStatus(IteratorWrapper* child) { void MergingIterator::AddToMaxHeapOrCheckStatus(IteratorWrapper* child) {
if (child->Valid()) { if (child->Valid()) {
assert(child->status().ok()); assert(child->status().ok());
maxHeap_->push(child); maxHeap_.push(child);
} else { } else {
considerStatus(child->status()); considerStatus(child->status());
} }
@ -354,7 +349,7 @@ void MergingIterator::AddToMaxHeapOrCheckStatus(IteratorWrapper* child) {
void MergingIterator::SwitchToForward() { void MergingIterator::SwitchToForward() {
// Otherwise, advance the non-current children. We advance current_ // Otherwise, advance the non-current children. We advance current_
// just after the if-block. // just after the if-block.
ClearHeaps(); InitMinHeap();
Slice target = key(); Slice target = key();
for (auto& child : children_) { for (auto& child : children_) {
if (&child != current_) { if (&child != current_) {
@ -370,7 +365,6 @@ void MergingIterator::SwitchToForward() {
} }
void MergingIterator::SwitchToBackward() { void MergingIterator::SwitchToBackward() {
ClearHeaps();
InitMaxHeap(); InitMaxHeap();
Slice target = key(); Slice target = key();
for (auto& child : children_) { for (auto& child : children_) {
@ -395,17 +389,37 @@ void MergingIterator::SwitchToBackward() {
assert(current_ == CurrentReverse()); assert(current_ == CurrentReverse());
} }
void MergingIterator::ClearHeaps() { void MergingIterator::InitMinHeap() {
minHeap_.clear(); #if 0
if (maxHeap_) { // this can be simplified because maxHeap_ and minHeap_ are physical identical,
maxHeap_->clear(); // the only difference between them are logical(the interpretation of comparator)
if (kReverse == direction_) {
maxHeap_.~MergerMaxIterHeap();
new(&minHeap_)MergerMinIterHeap(comparator_);
direction_ = kForward;
} }
else {
minHeap_.clear();
}
#else
minHeap_.clear();
#endif
} }
void MergingIterator::InitMaxHeap() { void MergingIterator::InitMaxHeap() {
if (!maxHeap_) { #if 0
maxHeap_.reset(new MergerMaxIterHeap(comparator_)); if (kForward == direction_) {
minHeap_.~MergerMinIterHeap();
new(&maxHeap_)MergerMaxIterHeap(comparator_);
direction_ = kReverse;
} }
else {
maxHeap_.clear();
}
#else
// use InitMinHeap(), because maxHeap_ and minHeap_ are physical identical
InitMinHeap();
#endif
} }
InternalIterator* NewMergingIterator(const InternalKeyComparator* cmp, InternalIterator* NewMergingIterator(const InternalKeyComparator* cmp,