Summary: While trying to reuse PinData() / ReleasePinnedData() .. to optimize away some memcpys I realized that there is a significant overhead for using PinData() / ReleasePinnedData if they were called many times. This diff refactor the pinning logic by introducing PinnedIteratorsManager a centralized component that will be created once and will be notified whenever we need to Pin an Iterator. This implementation have much less overhead than the original implementation Test Plan: make check -j64 COMPILE_WITH_ASAN=1 make check -j64 Reviewers: yhchiang, sdong, andrewkr Reviewed By: andrewkr Subscribers: andrewkr, dhruba Differential Revision: https://reviews.facebook.net/D56493main
parent
1995e34d6a
commit
d719b095dc
@ -0,0 +1,66 @@ |
|||||||
|
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
||||||
|
// This source code is licensed under the BSD-style license found in the
|
||||||
|
// LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
// of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
//
|
||||||
|
#pragma once |
||||||
|
#include <algorithm> |
||||||
|
#include <memory> |
||||||
|
#include <vector> |
||||||
|
|
||||||
|
#include "table/internal_iterator.h" |
||||||
|
|
||||||
|
namespace rocksdb { |
||||||
|
|
||||||
|
// PinnedIteratorsManager will be notified whenever we need to pin an Iterator
|
||||||
|
// and it will be responsible for deleting pinned Iterators when they are
|
||||||
|
// not needed anymore.
|
||||||
|
class PinnedIteratorsManager { |
||||||
|
public: |
||||||
|
PinnedIteratorsManager() : pinning_enabled(false), pinned_iters_(nullptr) {} |
||||||
|
~PinnedIteratorsManager() { assert(!pinning_enabled); } |
||||||
|
|
||||||
|
// Enable Iterators pinning
|
||||||
|
void StartPinning() { |
||||||
|
if (!pinning_enabled) { |
||||||
|
pinning_enabled = true; |
||||||
|
if (!pinned_iters_) { |
||||||
|
pinned_iters_.reset(new std::vector<InternalIterator*>()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Is pinning enabled ?
|
||||||
|
bool PinningEnabled() { return pinning_enabled; } |
||||||
|
|
||||||
|
// Take ownership of iter if pinning is enabled and delete it when
|
||||||
|
// ReleasePinnedIterators() is called
|
||||||
|
void PinIteratorIfNeeded(InternalIterator* iter) { |
||||||
|
if (!pinning_enabled || !iter) { |
||||||
|
return; |
||||||
|
} |
||||||
|
pinned_iters_->push_back(iter); |
||||||
|
} |
||||||
|
|
||||||
|
// Release pinned Iterators
|
||||||
|
void ReleasePinnedIterators() { |
||||||
|
if (pinning_enabled) { |
||||||
|
pinning_enabled = false; |
||||||
|
|
||||||
|
// Remove duplicate pointers
|
||||||
|
std::sort(pinned_iters_->begin(), pinned_iters_->end()); |
||||||
|
std::unique(pinned_iters_->begin(), pinned_iters_->end()); |
||||||
|
|
||||||
|
for (auto& iter : *pinned_iters_) { |
||||||
|
delete iter; |
||||||
|
} |
||||||
|
pinned_iters_->clear(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
bool pinning_enabled; |
||||||
|
std::unique_ptr<std::vector<InternalIterator*>> pinned_iters_; |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace rocksdb
|
Loading…
Reference in new issue