Allocate LevelFileIteratorState and LevelFileNumIterator from DB iterator's arena

Summary: Try to allocate LevelFileIteratorState and LevelFileNumIterator from DB iterator's arena, instead of calling malloc and free.

Test Plan: valgrind check

Reviewers: rven, yhchiang, anthony, kradhakrishnan, igor

Reviewed By: igor

Subscribers: leveldb, dhruba

Differential Revision: https://reviews.facebook.net/D40929
main
sdong 9 years ago
parent 436ed904da
commit 05e2831966
  1. 22
      db/version_set.cc
  2. 29
      table/two_level_iterator.cc
  3. 5
      table/two_level_iterator.h

@ -695,12 +695,14 @@ void Version::AddIterators(const ReadOptions& read_options,
return; return;
} }
auto* arena = merge_iter_builder->GetArena();
// Merge all level zero files together since they may overlap // Merge all level zero files together since they may overlap
for (size_t i = 0; i < storage_info_.LevelFilesBrief(0).num_files; i++) { for (size_t i = 0; i < storage_info_.LevelFilesBrief(0).num_files; i++) {
const auto& file = storage_info_.LevelFilesBrief(0).files[i]; const auto& file = storage_info_.LevelFilesBrief(0).files[i];
merge_iter_builder->AddIterator(cfd_->table_cache()->NewIterator( merge_iter_builder->AddIterator(cfd_->table_cache()->NewIterator(
read_options, soptions, cfd_->internal_comparator(), file.fd, nullptr, read_options, soptions, cfd_->internal_comparator(), file.fd, nullptr,
false, merge_iter_builder->GetArena())); false, arena));
} }
// For levels > 0, we can use a concatenating iterator that sequentially // For levels > 0, we can use a concatenating iterator that sequentially
@ -708,14 +710,16 @@ void Version::AddIterators(const ReadOptions& read_options,
// lazily. // lazily.
for (int level = 1; level < storage_info_.num_non_empty_levels(); level++) { for (int level = 1; level < storage_info_.num_non_empty_levels(); level++) {
if (storage_info_.LevelFilesBrief(level).num_files != 0) { if (storage_info_.LevelFilesBrief(level).num_files != 0) {
merge_iter_builder->AddIterator(NewTwoLevelIterator( auto* mem = arena->AllocateAligned(sizeof(LevelFileIteratorState));
new LevelFileIteratorState( auto* state = new (mem) LevelFileIteratorState(
cfd_->table_cache(), read_options, soptions, cfd_->table_cache(), read_options, soptions,
cfd_->internal_comparator(), false /* for_compaction */, cfd_->internal_comparator(), false /* for_compaction */,
cfd_->ioptions()->prefix_extractor != nullptr), cfd_->ioptions()->prefix_extractor != nullptr);
new LevelFileNumIterator(cfd_->internal_comparator(), mem = arena->AllocateAligned(sizeof(LevelFileNumIterator));
&storage_info_.LevelFilesBrief(level)), auto* first_level_iter = new (mem) LevelFileNumIterator(
merge_iter_builder->GetArena())); cfd_->internal_comparator(), &storage_info_.LevelFilesBrief(level));
merge_iter_builder->AddIterator(
NewTwoLevelIterator(state, first_level_iter, arena, false));
} }
} }
} }

@ -22,11 +22,17 @@ namespace {
class TwoLevelIterator: public Iterator { class TwoLevelIterator: public Iterator {
public: public:
explicit TwoLevelIterator(TwoLevelIteratorState* state, explicit TwoLevelIterator(TwoLevelIteratorState* state,
Iterator* first_level_iter); Iterator* first_level_iter,
bool need_free_iter_and_state);
virtual ~TwoLevelIterator() { virtual ~TwoLevelIterator() {
first_level_iter_.DeleteIter(false); first_level_iter_.DeleteIter(!need_free_iter_and_state_);
second_level_iter_.DeleteIter(false); second_level_iter_.DeleteIter(false);
if (need_free_iter_and_state_) {
delete state_;
} else {
state_->~TwoLevelIteratorState();
}
} }
virtual void Seek(const Slice& target) override; virtual void Seek(const Slice& target) override;
@ -65,9 +71,10 @@ class TwoLevelIterator: public Iterator {
void SetSecondLevelIterator(Iterator* iter); void SetSecondLevelIterator(Iterator* iter);
void InitDataBlock(); void InitDataBlock();
std::unique_ptr<TwoLevelIteratorState> state_; TwoLevelIteratorState* state_;
IteratorWrapper first_level_iter_; IteratorWrapper first_level_iter_;
IteratorWrapper second_level_iter_; // May be nullptr IteratorWrapper second_level_iter_; // May be nullptr
bool need_free_iter_and_state_;
Status status_; Status status_;
// If second_level_iter is non-nullptr, then "data_block_handle_" holds the // If second_level_iter is non-nullptr, then "data_block_handle_" holds the
// "index_value" passed to block_function_ to create the second_level_iter. // "index_value" passed to block_function_ to create the second_level_iter.
@ -75,8 +82,11 @@ class TwoLevelIterator: public Iterator {
}; };
TwoLevelIterator::TwoLevelIterator(TwoLevelIteratorState* state, TwoLevelIterator::TwoLevelIterator(TwoLevelIteratorState* state,
Iterator* first_level_iter) Iterator* first_level_iter,
: state_(state), first_level_iter_(first_level_iter) {} bool need_free_iter_and_state)
: state_(state),
first_level_iter_(first_level_iter),
need_free_iter_and_state_(need_free_iter_and_state) {}
void TwoLevelIterator::Seek(const Slice& target) { void TwoLevelIterator::Seek(const Slice& target) {
if (state_->check_prefix_may_match && if (state_->check_prefix_may_match &&
@ -186,12 +196,15 @@ void TwoLevelIterator::InitDataBlock() {
} // namespace } // namespace
Iterator* NewTwoLevelIterator(TwoLevelIteratorState* state, Iterator* NewTwoLevelIterator(TwoLevelIteratorState* state,
Iterator* first_level_iter, Arena* arena) { Iterator* first_level_iter, Arena* arena,
bool need_free_iter_and_state) {
if (arena == nullptr) { if (arena == nullptr) {
return new TwoLevelIterator(state, first_level_iter); return new TwoLevelIterator(state, first_level_iter,
need_free_iter_and_state);
} else { } else {
auto mem = arena->AllocateAligned(sizeof(TwoLevelIterator)); auto mem = arena->AllocateAligned(sizeof(TwoLevelIterator));
return new (mem) TwoLevelIterator(state, first_level_iter); return new (mem)
TwoLevelIterator(state, first_level_iter, need_free_iter_and_state);
} }
} }

@ -43,8 +43,11 @@ struct TwoLevelIteratorState {
// arena: If not null, the arena is used to allocate the Iterator. // arena: If not null, the arena is used to allocate the Iterator.
// When destroying the iterator, the destructor will destroy // When destroying the iterator, the destructor will destroy
// all the states but those allocated in arena. // all the states but those allocated in arena.
// need_free_iter_and_state: free `state` and `first_level_iter` if
// true. Otherwise, just call destructor.
extern Iterator* NewTwoLevelIterator(TwoLevelIteratorState* state, extern Iterator* NewTwoLevelIterator(TwoLevelIteratorState* state,
Iterator* first_level_iter, Iterator* first_level_iter,
Arena* arena = nullptr); Arena* arena = nullptr,
bool need_free_iter_and_state = true);
} // namespace rocksdb } // namespace rocksdb

Loading…
Cancel
Save