class Block to store num_restarts_

Summary:
Right now, every Block::NewIterator() reads num_restarts_ from the block, which is already read in Block::Block(). This sometimes cause a CPU cache miss. Although fetching this cacheline can usually benefit follow-up block restart offset reading, as they are close to each other, it's almost free to get ride of this read by storing it in the Block class.
Closes https://github.com/facebook/rocksdb/pull/3869

Differential Revision: D8052493

Pulled By: siying

fbshipit-source-id: 9c72360f0c2d7329f3c198ce4eaedd2bc14b87c1
main
Siying Dong 7 years ago committed by Facebook Github Bot
parent a0c7b4d526
commit 26da3676d9
  1. 9
      table/block.cc
  2. 1
      table/block.h

@ -402,12 +402,14 @@ Block::Block(BlockContents&& contents, SequenceNumber _global_seqno,
data_(contents_.data.data()), data_(contents_.data.data()),
size_(contents_.data.size()), size_(contents_.data.size()),
restart_offset_(0), restart_offset_(0),
num_restarts_(0),
global_seqno_(_global_seqno) { global_seqno_(_global_seqno) {
if (size_ < sizeof(uint32_t)) { if (size_ < sizeof(uint32_t)) {
size_ = 0; // Error marker size_ = 0; // Error marker
} else { } else {
num_restarts_ = NumRestarts();
restart_offset_ = restart_offset_ =
static_cast<uint32_t>(size_) - (1 + NumRestarts()) * sizeof(uint32_t); static_cast<uint32_t>(size_) - (1 + num_restarts_) * sizeof(uint32_t);
if (restart_offset_ > size_ - sizeof(uint32_t)) { if (restart_offset_ > size_ - sizeof(uint32_t)) {
// The size is too small for NumRestarts() and therefore // The size is too small for NumRestarts() and therefore
// restart_offset_ wrapped around. // restart_offset_ wrapped around.
@ -432,15 +434,14 @@ BlockIter* Block::NewIterator(const Comparator* cmp, BlockIter* iter,
ret_iter->Invalidate(Status::Corruption("bad block contents")); ret_iter->Invalidate(Status::Corruption("bad block contents"));
return ret_iter; return ret_iter;
} }
const uint32_t num_restarts = NumRestarts(); if (num_restarts_ == 0) {
if (num_restarts == 0) {
// Empty block. // Empty block.
ret_iter->Invalidate(Status::OK()); ret_iter->Invalidate(Status::OK());
return ret_iter; return ret_iter;
} else { } else {
BlockPrefixIndex* prefix_index_ptr = BlockPrefixIndex* prefix_index_ptr =
total_order_seek ? nullptr : prefix_index_.get(); total_order_seek ? nullptr : prefix_index_.get();
ret_iter->Initialize(cmp, data_, restart_offset_, num_restarts, ret_iter->Initialize(cmp, data_, restart_offset_, num_restarts_,
prefix_index_ptr, global_seqno_, prefix_index_ptr, global_seqno_,
read_amp_bitmap_.get()); read_amp_bitmap_.get());

@ -184,6 +184,7 @@ class Block {
const char* data_; // contents_.data.data() const char* data_; // contents_.data.data()
size_t size_; // contents_.data.size() size_t size_; // contents_.data.size()
uint32_t restart_offset_; // Offset in data_ of restart array uint32_t restart_offset_; // Offset in data_ of restart array
uint32_t num_restarts_;
std::unique_ptr<BlockPrefixIndex> prefix_index_; std::unique_ptr<BlockPrefixIndex> prefix_index_;
std::unique_ptr<BlockReadAmpBitmap> read_amp_bitmap_; std::unique_ptr<BlockReadAmpBitmap> read_amp_bitmap_;
// All keys in the block will have seqno = global_seqno_, regardless of // All keys in the block will have seqno = global_seqno_, regardless of

Loading…
Cancel
Save