caf0f53a74
Summary: Given that index value is a BlockHandle, which is basically an <offset, size> pair we can apply delta encoding on the values. The first value at each index restart interval encoded the full BlockHandle but the rest encode only the size. Refer to IndexBlockIter::DecodeCurrentValue for the detail of the encoding. This reduces the index size which helps using the block cache more efficiently. The feature is enabled with using format_version 4. The feature comes with a bit of cpu overhead which should be paid back by the higher cache hits due to smaller index block size. Results with sysbench read-only using 4k blocks and using 16 index restart interval: Format 2: 19585 rocksdb read-only range=100 Format 3: 19569 rocksdb read-only range=100 Format 4: 19352 rocksdb read-only range=100 Pull Request resolved: https://github.com/facebook/rocksdb/pull/3983 Differential Revision: D8361343 Pulled By: maysamyabandeh fbshipit-source-id: f882ee082322acac32b0072e2bdbb0b5f854e651
112 lines
3.2 KiB
C++
112 lines
3.2 KiB
C++
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
|
// This source code is licensed under both the GPLv2 (found in the
|
|
// COPYING file in the root directory) and Apache 2.0 License
|
|
// (found in the LICENSE.Apache file in the root directory).
|
|
//
|
|
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
|
|
|
#pragma once
|
|
|
|
#include <set>
|
|
|
|
#include "table/internal_iterator.h"
|
|
|
|
namespace rocksdb {
|
|
|
|
// A internal wrapper class with an interface similar to Iterator that caches
|
|
// the valid() and key() results for an underlying iterator.
|
|
// This can help avoid virtual function calls and also gives better
|
|
// cache locality.
|
|
template <class TValue = Slice>
|
|
class IteratorWrapperBase {
|
|
public:
|
|
IteratorWrapperBase() : iter_(nullptr), valid_(false) {}
|
|
explicit IteratorWrapperBase(InternalIteratorBase<TValue>* _iter)
|
|
: iter_(nullptr) {
|
|
Set(_iter);
|
|
}
|
|
~IteratorWrapperBase() {}
|
|
InternalIteratorBase<TValue>* iter() const { return iter_; }
|
|
|
|
// Set the underlying Iterator to _iter and return
|
|
// previous underlying Iterator.
|
|
InternalIteratorBase<TValue>* Set(InternalIteratorBase<TValue>* _iter) {
|
|
InternalIteratorBase<TValue>* old_iter = iter_;
|
|
|
|
iter_ = _iter;
|
|
if (iter_ == nullptr) {
|
|
valid_ = false;
|
|
} else {
|
|
Update();
|
|
}
|
|
return old_iter;
|
|
}
|
|
|
|
void DeleteIter(bool is_arena_mode) {
|
|
if (iter_) {
|
|
if (!is_arena_mode) {
|
|
delete iter_;
|
|
} else {
|
|
iter_->~InternalIteratorBase<TValue>();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Iterator interface methods
|
|
bool Valid() const { return valid_; }
|
|
Slice key() const { assert(Valid()); return key_; }
|
|
TValue value() const {
|
|
assert(Valid());
|
|
return iter_->value();
|
|
}
|
|
// Methods below require iter() != nullptr
|
|
Status status() const { assert(iter_); return iter_->status(); }
|
|
void Next() { assert(iter_); iter_->Next(); Update(); }
|
|
void Prev() { assert(iter_); iter_->Prev(); Update(); }
|
|
void Seek(const Slice& k) { assert(iter_); iter_->Seek(k); Update(); }
|
|
void SeekForPrev(const Slice& k) {
|
|
assert(iter_);
|
|
iter_->SeekForPrev(k);
|
|
Update();
|
|
}
|
|
void SeekToFirst() { assert(iter_); iter_->SeekToFirst(); Update(); }
|
|
void SeekToLast() { assert(iter_); iter_->SeekToLast(); Update(); }
|
|
|
|
void SetPinnedItersMgr(PinnedIteratorsManager* pinned_iters_mgr) {
|
|
assert(iter_);
|
|
iter_->SetPinnedItersMgr(pinned_iters_mgr);
|
|
}
|
|
bool IsKeyPinned() const {
|
|
assert(Valid());
|
|
return iter_->IsKeyPinned();
|
|
}
|
|
bool IsValuePinned() const {
|
|
assert(Valid());
|
|
return iter_->IsValuePinned();
|
|
}
|
|
|
|
private:
|
|
void Update() {
|
|
valid_ = iter_->Valid();
|
|
if (valid_) {
|
|
key_ = iter_->key();
|
|
assert(iter_->status().ok());
|
|
}
|
|
}
|
|
|
|
InternalIteratorBase<TValue>* iter_;
|
|
bool valid_;
|
|
Slice key_;
|
|
};
|
|
|
|
using IteratorWrapper = IteratorWrapperBase<Slice>;
|
|
|
|
class Arena;
|
|
// Return an empty iterator (yields nothing) allocated from arena.
|
|
template <class TValue = Slice>
|
|
extern InternalIteratorBase<TValue>* NewEmptyInternalIterator(Arena* arena);
|
|
|
|
} // namespace rocksdb
|