|
|
|
// 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.
|
|
|
|
// This source code is also licensed under the GPLv2 license found in the
|
|
|
|
// COPYING file in the root directory of this source tree.
|
|
|
|
|
|
|
|
#include "util/sync_point.h"
|
|
|
|
#include <functional>
|
|
|
|
#include <thread>
|
Move rate_limiter, write buffering, most perf context instrumentation and most random kill out of Env
Summary: We want to keep Env a think layer for better portability. Less platform dependent codes should be moved out of Env. In this patch, I create a wrapper of file readers and writers, and put rate limiting, write buffering, as well as most perf context instrumentation and random kill out of Env. It will make it easier to maintain multiple Env in the future.
Test Plan: Run all existing unit tests.
Reviewers: anthony, kradhakrishnan, IslamAbdelRahman, yhchiang, igor
Reviewed By: igor
Subscribers: leveldb, dhruba
Differential Revision: https://reviews.facebook.net/D42321
9 years ago
|
|
|
#include "port/port.h"
|
|
|
|
#include "util/random.h"
|
|
|
|
|
|
|
|
int rocksdb_kill_odds = 0;
|
|
|
|
std::vector<std::string> rocksdb_kill_prefix_blacklist;
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
namespace rocksdb {
|
|
|
|
|
|
|
|
void TestKillRandom(std::string kill_point, int odds,
|
|
|
|
const std::string& srcfile, int srcline) {
|
|
|
|
for (auto& p : rocksdb_kill_prefix_blacklist) {
|
|
|
|
if (kill_point.substr(0, p.length()) == p) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Move rate_limiter, write buffering, most perf context instrumentation and most random kill out of Env
Summary: We want to keep Env a think layer for better portability. Less platform dependent codes should be moved out of Env. In this patch, I create a wrapper of file readers and writers, and put rate limiting, write buffering, as well as most perf context instrumentation and random kill out of Env. It will make it easier to maintain multiple Env in the future.
Test Plan: Run all existing unit tests.
Reviewers: anthony, kradhakrishnan, IslamAbdelRahman, yhchiang, igor
Reviewed By: igor
Subscribers: leveldb, dhruba
Differential Revision: https://reviews.facebook.net/D42321
9 years ago
|
|
|
assert(odds > 0);
|
|
|
|
if (odds % 7 == 0) {
|
Crash test to make kill decision for every kill point
Summary:
In crash test, when coming to each kill point, we start a random class using seed as current second. With this approach, for every second, the random number used is the same. However, in each second, there are multiple kill points with different frequency. It makes it hard to reason about chance of kill point to trigger. With this commit, we use thread local random seed to generate the random number, so that it will take different values per second, hoping it makes chances of killing much easier to reason about.
Also significantly reduce the kill odd to make sure time before kiling is similar as before.
Test Plan: Run white box crash test and see the killing happens as expected and the run time time before killing reasonable.
Reviewers: kradhakrishnan, IslamAbdelRahman, rven, yhchiang, andrewkr, anthony
Reviewed By: anthony
Subscribers: leveldb, dhruba
Differential Revision: https://reviews.facebook.net/D52971
9 years ago
|
|
|
// class Random uses multiplier 16807, which is 7^5. If odds are
|
|
|
|
// multiplier of 7, there might be limited values generated.
|
|
|
|
odds++;
|
|
|
|
}
|
Crash test to make kill decision for every kill point
Summary:
In crash test, when coming to each kill point, we start a random class using seed as current second. With this approach, for every second, the random number used is the same. However, in each second, there are multiple kill points with different frequency. It makes it hard to reason about chance of kill point to trigger. With this commit, we use thread local random seed to generate the random number, so that it will take different values per second, hoping it makes chances of killing much easier to reason about.
Also significantly reduce the kill odd to make sure time before kiling is similar as before.
Test Plan: Run white box crash test and see the killing happens as expected and the run time time before killing reasonable.
Reviewers: kradhakrishnan, IslamAbdelRahman, rven, yhchiang, andrewkr, anthony
Reviewed By: anthony
Subscribers: leveldb, dhruba
Differential Revision: https://reviews.facebook.net/D52971
9 years ago
|
|
|
auto* r = Random::GetTLSInstance();
|
|
|
|
bool crash = r->OneIn(odds);
|
Move rate_limiter, write buffering, most perf context instrumentation and most random kill out of Env
Summary: We want to keep Env a think layer for better portability. Less platform dependent codes should be moved out of Env. In this patch, I create a wrapper of file readers and writers, and put rate limiting, write buffering, as well as most perf context instrumentation and random kill out of Env. It will make it easier to maintain multiple Env in the future.
Test Plan: Run all existing unit tests.
Reviewers: anthony, kradhakrishnan, IslamAbdelRahman, yhchiang, igor
Reviewed By: igor
Subscribers: leveldb, dhruba
Differential Revision: https://reviews.facebook.net/D42321
9 years ago
|
|
|
if (crash) {
|
|
|
|
port::Crash(srcfile, srcline);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SyncPoint* SyncPoint::GetInstance() {
|
|
|
|
static SyncPoint sync_point;
|
|
|
|
return &sync_point;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SyncPoint::LoadDependency(const std::vector<SyncPointPair>& dependencies) {
|
|
|
|
std::unique_lock<std::mutex> lock(mutex_);
|
|
|
|
successors_.clear();
|
|
|
|
predecessors_.clear();
|
|
|
|
cleared_points_.clear();
|
|
|
|
for (const auto& dependency : dependencies) {
|
|
|
|
successors_[dependency.predecessor].push_back(dependency.successor);
|
|
|
|
predecessors_[dependency.successor].push_back(dependency.predecessor);
|
|
|
|
}
|
|
|
|
cv_.notify_all();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SyncPoint::LoadDependencyAndMarkers(
|
|
|
|
const std::vector<SyncPointPair>& dependencies,
|
|
|
|
const std::vector<SyncPointPair>& markers) {
|
|
|
|
std::unique_lock<std::mutex> lock(mutex_);
|
|
|
|
successors_.clear();
|
|
|
|
predecessors_.clear();
|
|
|
|
cleared_points_.clear();
|
|
|
|
markers_.clear();
|
|
|
|
marked_thread_id_.clear();
|
|
|
|
for (const auto& dependency : dependencies) {
|
|
|
|
successors_[dependency.predecessor].push_back(dependency.successor);
|
|
|
|
predecessors_[dependency.successor].push_back(dependency.predecessor);
|
|
|
|
}
|
|
|
|
for (const auto& marker : markers) {
|
|
|
|
successors_[marker.predecessor].push_back(marker.successor);
|
|
|
|
predecessors_[marker.successor].push_back(marker.predecessor);
|
|
|
|
markers_[marker.predecessor].push_back(marker.successor);
|
|
|
|
}
|
|
|
|
cv_.notify_all();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SyncPoint::PredecessorsAllCleared(const std::string& point) {
|
|
|
|
for (const auto& pred : predecessors_[point]) {
|
|
|
|
if (cleared_points_.count(pred) == 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
options.level_compaction_dynamic_level_bytes to allow RocksDB to pick size bases of levels dynamically.
Summary:
When having fixed max_bytes_for_level_base, the ratio of size of largest level and the second one can range from 0 to the multiplier. This makes LSM tree frequently irregular and unpredictable. It can also cause poor space amplification in some cases.
In this improvement (proposed by Igor Kabiljo), we introduce a parameter option.level_compaction_use_dynamic_max_bytes. When turning it on, RocksDB is free to pick a level base in the range of (options.max_bytes_for_level_base/options.max_bytes_for_level_multiplier, options.max_bytes_for_level_base] so that real level ratios are close to options.max_bytes_for_level_multiplier.
Test Plan: New unit tests and pass tests suites including valgrind.
Reviewers: MarkCallaghan, rven, yhchiang, igor, ikabiljo
Reviewed By: ikabiljo
Subscribers: yoshinorim, ikabiljo, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D31437
10 years ago
|
|
|
void SyncPoint::SetCallBack(const std::string point,
|
|
|
|
std::function<void(void*)> callback) {
|
options.level_compaction_dynamic_level_bytes to allow RocksDB to pick size bases of levels dynamically.
Summary:
When having fixed max_bytes_for_level_base, the ratio of size of largest level and the second one can range from 0 to the multiplier. This makes LSM tree frequently irregular and unpredictable. It can also cause poor space amplification in some cases.
In this improvement (proposed by Igor Kabiljo), we introduce a parameter option.level_compaction_use_dynamic_max_bytes. When turning it on, RocksDB is free to pick a level base in the range of (options.max_bytes_for_level_base/options.max_bytes_for_level_multiplier, options.max_bytes_for_level_base] so that real level ratios are close to options.max_bytes_for_level_multiplier.
Test Plan: New unit tests and pass tests suites including valgrind.
Reviewers: MarkCallaghan, rven, yhchiang, igor, ikabiljo
Reviewed By: ikabiljo
Subscribers: yoshinorim, ikabiljo, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D31437
10 years ago
|
|
|
std::unique_lock<std::mutex> lock(mutex_);
|
|
|
|
callbacks_[point] = callback;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SyncPoint::ClearAllCallBacks() {
|
|
|
|
std::unique_lock<std::mutex> lock(mutex_);
|
|
|
|
while (num_callbacks_running_ > 0) {
|
|
|
|
cv_.wait(lock);
|
|
|
|
}
|
|
|
|
callbacks_.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SyncPoint::EnableProcessing() {
|
|
|
|
std::unique_lock<std::mutex> lock(mutex_);
|
|
|
|
enabled_ = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SyncPoint::DisableProcessing() {
|
|
|
|
std::unique_lock<std::mutex> lock(mutex_);
|
|
|
|
enabled_ = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SyncPoint::ClearTrace() {
|
|
|
|
std::unique_lock<std::mutex> lock(mutex_);
|
|
|
|
cleared_points_.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SyncPoint::DisabledByMarker(const std::string& point,
|
|
|
|
std::thread::id thread_id) {
|
|
|
|
auto marked_point_iter = marked_thread_id_.find(point);
|
|
|
|
return marked_point_iter != marked_thread_id_.end() &&
|
|
|
|
thread_id != marked_point_iter->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SyncPoint::Process(const std::string& point, void* cb_arg) {
|
|
|
|
std::unique_lock<std::mutex> lock(mutex_);
|
|
|
|
if (!enabled_) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto thread_id = std::this_thread::get_id();
|
|
|
|
|
|
|
|
auto marker_iter = markers_.find(point);
|
|
|
|
if (marker_iter != markers_.end()) {
|
|
|
|
for (auto marked_point : marker_iter->second) {
|
|
|
|
marked_thread_id_.insert(std::make_pair(marked_point, thread_id));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DisabledByMarker(point, thread_id)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (!PredecessorsAllCleared(point)) {
|
|
|
|
cv_.wait(lock);
|
|
|
|
if (DisabledByMarker(point, thread_id)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
options.level_compaction_dynamic_level_bytes to allow RocksDB to pick size bases of levels dynamically.
Summary:
When having fixed max_bytes_for_level_base, the ratio of size of largest level and the second one can range from 0 to the multiplier. This makes LSM tree frequently irregular and unpredictable. It can also cause poor space amplification in some cases.
In this improvement (proposed by Igor Kabiljo), we introduce a parameter option.level_compaction_use_dynamic_max_bytes. When turning it on, RocksDB is free to pick a level base in the range of (options.max_bytes_for_level_base/options.max_bytes_for_level_multiplier, options.max_bytes_for_level_base] so that real level ratios are close to options.max_bytes_for_level_multiplier.
Test Plan: New unit tests and pass tests suites including valgrind.
Reviewers: MarkCallaghan, rven, yhchiang, igor, ikabiljo
Reviewed By: ikabiljo
Subscribers: yoshinorim, ikabiljo, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D31437
10 years ago
|
|
|
auto callback_pair = callbacks_.find(point);
|
|
|
|
if (callback_pair != callbacks_.end()) {
|
|
|
|
num_callbacks_running_++;
|
|
|
|
mutex_.unlock();
|
|
|
|
callback_pair->second(cb_arg);
|
options.level_compaction_dynamic_level_bytes to allow RocksDB to pick size bases of levels dynamically.
Summary:
When having fixed max_bytes_for_level_base, the ratio of size of largest level and the second one can range from 0 to the multiplier. This makes LSM tree frequently irregular and unpredictable. It can also cause poor space amplification in some cases.
In this improvement (proposed by Igor Kabiljo), we introduce a parameter option.level_compaction_use_dynamic_max_bytes. When turning it on, RocksDB is free to pick a level base in the range of (options.max_bytes_for_level_base/options.max_bytes_for_level_multiplier, options.max_bytes_for_level_base] so that real level ratios are close to options.max_bytes_for_level_multiplier.
Test Plan: New unit tests and pass tests suites including valgrind.
Reviewers: MarkCallaghan, rven, yhchiang, igor, ikabiljo
Reviewed By: ikabiljo
Subscribers: yoshinorim, ikabiljo, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D31437
10 years ago
|
|
|
mutex_.lock();
|
|
|
|
num_callbacks_running_--;
|
|
|
|
cv_.notify_all();
|
|
|
|
}
|
|
|
|
|
|
|
|
cleared_points_.insert(point);
|
|
|
|
cv_.notify_all();
|
|
|
|
}
|
|
|
|
} // namespace rocksdb
|
|
|
|
#endif // NDEBUG
|