Skip to content

Commit

Permalink
Fix a perf regression that caused every key to go through upper bound…
Browse files Browse the repository at this point in the history
… check (facebook#7209)

Summary:
facebook#5289 introduces a performance regression that caused an upper bound check within every BlockBasedTableIterator::Next(). This is unnecessary if we've checked the boundary key for current block and it is within upper bound.

Fix the bug. Also rename the boolean to a enum so that the code is slightly better readable. The original regression was probably to fix a bug that the block upper bound check status is not reset after a new block is created. Fix it bug so that the regression can be avoided without hitting the bug.

Pull Request resolved: facebook#7209

Test Plan: Run all existing tests. Will run atomic black box crash test for a while.

Reviewed By: anand1976

Differential Revision: D22859246

fbshipit-source-id: cbdad1f5e656c55fd8b71726d5a4f6cb53ff9140
  • Loading branch information
siying authored and facebook-github-bot committed Aug 4, 2020
1 parent fea286d commit 41c328f
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 10 deletions.
3 changes: 3 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Rocksdb Change Log
## Unreleased
### Bug fixes
* Fix a performance regression introduced in 6.4 that makes a upper bound check for every Next() even if keys are within a data block that is within the upper bound.


## 6.12 (2020-07-28)
### Public API Change
Expand Down
18 changes: 11 additions & 7 deletions table/block_based/block_based_table_iterator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,8 @@ void BlockBasedTableIterator::FindBlockForward() {
// Whether next data block is out of upper bound, if there is one.
const bool next_block_is_out_of_bound =
read_options_.iterate_upper_bound != nullptr &&
block_iter_points_to_real_block_ && !data_block_within_upper_bound_;
block_iter_points_to_real_block_ &&
block_upper_bound_check_ == BlockUpperBound::kUpperBoundInCurBlock;
assert(!next_block_is_out_of_bound ||
user_comparator_.CompareWithoutTimestamp(
*read_options_.iterate_upper_bound, /*a_has_ts=*/false,
Expand Down Expand Up @@ -358,7 +359,9 @@ void BlockBasedTableIterator::FindKeyBackward() {
}

void BlockBasedTableIterator::CheckOutOfBound() {
if (read_options_.iterate_upper_bound != nullptr && Valid()) {
if (read_options_.iterate_upper_bound != nullptr &&
block_upper_bound_check_ != BlockUpperBound::kUpperBoundBeyondCurBlock &&
Valid()) {
is_out_of_bound_ =
user_comparator_.CompareWithoutTimestamp(
*read_options_.iterate_upper_bound, /*a_has_ts=*/false, user_key(),
Expand All @@ -369,11 +372,12 @@ void BlockBasedTableIterator::CheckOutOfBound() {
void BlockBasedTableIterator::CheckDataBlockWithinUpperBound() {
if (read_options_.iterate_upper_bound != nullptr &&
block_iter_points_to_real_block_) {
data_block_within_upper_bound_ =
(user_comparator_.CompareWithoutTimestamp(
*read_options_.iterate_upper_bound, /*a_has_ts=*/false,
index_iter_->user_key(),
/*b_has_ts=*/true) > 0);
block_upper_bound_check_ = (user_comparator_.CompareWithoutTimestamp(
*read_options_.iterate_upper_bound,
/*a_has_ts=*/false, index_iter_->user_key(),
/*b_has_ts=*/true) > 0)
? BlockUpperBound::kUpperBoundBeyondCurBlock
: BlockUpperBound::kUpperBoundInCurBlock;
}
}
} // namespace ROCKSDB_NAMESPACE
37 changes: 34 additions & 3 deletions table/block_based/block_based_table_iterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ class BlockBasedTableIterator : public InternalIteratorBase<Slice> {

inline bool MayBeOutOfUpperBound() override {
assert(Valid());
return !data_block_within_upper_bound_;
return block_upper_bound_check_ !=
BlockUpperBound::kUpperBoundBeyondCurBlock;
}

void SetPinnedItersMgr(PinnedIteratorsManager* pinned_iters_mgr) override {
Expand Down Expand Up @@ -134,6 +135,7 @@ class BlockBasedTableIterator : public InternalIteratorBase<Slice> {
block_iter_.Invalidate(Status::OK());
block_iter_points_to_real_block_ = false;
}
block_upper_bound_check_ = BlockUpperBound::kUnknown;
}

void SavePrevIndexValue() {
Expand All @@ -149,6 +151,34 @@ class BlockBasedTableIterator : public InternalIteratorBase<Slice> {
kForward,
kBackward,
};
// This enum indicates whether the upper bound falls into current block
// or beyond.
// +-------------+
// | cur block | <-- (1)
// +-------------+
// <-- (2)
// --- <boundary key> ---
// <-- (3)
// +-------------+
// | next block | <-- (4)
// ......
//
// When the block is smaller than <boundary key>, kUpperBoundInCurBlock
// is the value to use. The examples are (1) or (2) in the graph. It means
// all keys in the next block or beyond will be out of bound. Keys within
// the current block may or may not be out of bound.
// When the block is larger or equal to <boundary key>,
// kUpperBoundBeyondCurBlock is to be used. The examples are (3) and (4)
// in the graph. It means that all keys in the current block is within the
// upper bound and keys in the next block may or may not be within the uppder
// bound.
// If the boundary key hasn't been checked against the upper bound,
// kUnknown can be used.
enum class BlockUpperBound {
kUpperBoundInCurBlock,
kUpperBoundBeyondCurBlock,
kUnknown,
};

const BlockBasedTable* table_;
const ReadOptions& read_options_;
Expand All @@ -169,8 +199,9 @@ class BlockBasedTableIterator : public InternalIteratorBase<Slice> {
bool block_iter_points_to_real_block_;
// See InternalIteratorBase::IsOutOfBound().
bool is_out_of_bound_ = false;
// Whether current data block being fully within iterate upper bound.
bool data_block_within_upper_bound_ = false;
// How current data block's boundary key with the next block is compared with
// iterate upper bound.
BlockUpperBound block_upper_bound_check_ = BlockUpperBound::kUnknown;
// True if we're standing at the first key of a block, and we haven't loaded
// that block yet. A call to PrepareValue() will trigger loading the block.
bool is_at_first_key_from_index_ = false;
Expand Down

0 comments on commit 41c328f

Please sign in to comment.