[RocksDB] Introduce Fast Mutex option

Summary:
This diff adds an option to specify whether PTHREAD_MUTEX_ADAPTIVE_NP will be enabled for the rocksdb single big kernel lock. db_bench also have this option now.
Quickly tested 8 thread cpu bound 100 byte random read.
No fast mutex: ~750k/s ops
With fast mutex: ~880k/s ops

Test Plan: make check; db_bench; db_stress

Reviewers: dhruba

CC: MarkCallaghan, leveldb

Differential Revision: https://reviews.facebook.net/D11031
This commit is contained in:
Haobo Xu 2013-05-31 16:30:17 -07:00
parent ab8d2f6ab2
commit d897d33bf1
6 changed files with 42 additions and 3 deletions

View File

@ -301,6 +301,10 @@ static bool FLAGS_advise_random_on_open =
static auto FLAGS_compaction_fadvice =
leveldb::Options().access_hint_on_compaction_start;
// Use adaptive mutex
static auto FLAGS_use_adaptive_mutex =
leveldb::Options().use_adaptive_mutex;
namespace leveldb {
// Helper for quickly generating random data.
@ -1149,6 +1153,9 @@ unique_ptr<char []> GenerateKeyFromInt(int v, const char* suffix = "")
options.allow_readahead_compactions = FLAGS_use_readahead_compactions;
options.advise_random_on_open = FLAGS_advise_random_on_open;
options.access_hint_on_compaction_start = FLAGS_compaction_fadvice;
options.use_adaptive_mutex = FLAGS_use_adaptive_mutex;
Status s;
if(FLAGS_read_only) {
s = DB::OpenForReadOnly(options, FLAGS_db, &db_);
@ -1958,6 +1965,9 @@ int main(int argc, char** argv) {
else {
fprintf(stdout, "Unknown compaction fadvice:%s\n", buf);
}
} else if (sscanf(argv[i], "--use_adaptive_mutex=%d%c", &n, &junk) == 1
&& (n == 0 || n ==1 )) {
FLAGS_use_adaptive_mutex = n;
} else {
fprintf(stderr, "Invalid flag '%s'\n", argv[i]);
exit(1);

View File

@ -153,6 +153,7 @@ DBImpl::DBImpl(const Options& options, const std::string& dbname)
internal_filter_policy_(options.filter_policy),
owns_info_log_(options_.info_log != options.info_log),
db_lock_(nullptr),
mutex_(options.use_adaptive_mutex),
shutting_down_(nullptr),
bg_cv_(&mutex_),
mem_(new MemTable(internal_comparator_, NumberLevels())),

View File

@ -451,6 +451,14 @@ struct Options {
// It will be applied to all input files of a compaction.
// Default: NORMAL
enum { NONE, NORMAL, SEQUENTIAL, WILLNEED } access_hint_on_compaction_start;
// Use adaptive mutex, which spins in the user space before resorting
// to kernel. This could reduce context switch when the mutex is not
// heavily contended. However, if the mutex is hot, we could end up
// wasting spin time.
// Default: false
bool use_adaptive_mutex;
};
// Options that control read operations

View File

@ -19,7 +19,24 @@ static void PthreadCall(const char* label, int result) {
}
}
Mutex::Mutex() { PthreadCall("init mutex", pthread_mutex_init(&mu_, NULL)); }
Mutex::Mutex(bool adaptive) {
#ifdef OS_LINUX
if (!adaptive) {
PthreadCall("init mutex", pthread_mutex_init(&mu_, NULL));
} else {
pthread_mutexattr_t mutex_attr;
PthreadCall("init mutex attr", pthread_mutexattr_init(&mutex_attr));
PthreadCall("set mutex attr",
pthread_mutexattr_settype(&mutex_attr,
PTHREAD_MUTEX_ADAPTIVE_NP));
PthreadCall("init mutex", pthread_mutex_init(&mu_, &mutex_attr));
PthreadCall("destroy mutex attr",
pthread_mutexattr_destroy(&mutex_attr));
}
#else // ignore adaptive for non-linux platform
PthreadCall("init mutex", pthread_mutex_init(&mu_, NULL));
#endif // OS_LINUX
}
Mutex::~Mutex() { PthreadCall("destroy mutex", pthread_mutex_destroy(&mu_)); }

View File

@ -82,7 +82,7 @@ class CondVar;
class Mutex {
public:
Mutex();
Mutex(bool adaptive = false);
~Mutex();
void Lock();

View File

@ -73,7 +73,8 @@ Options::Options()
stats_dump_period_sec(3600),
block_size_deviation (10),
advise_random_on_open(true),
access_hint_on_compaction_start(NORMAL) {
access_hint_on_compaction_start(NORMAL),
use_adaptive_mutex(false) {
}
static const char* const access_hints[] = {
@ -208,6 +209,8 @@ Options::Dump(Logger* log) const
advise_random_on_open);
Log(log," Options.access_hint_on_compaction_start: %s",
access_hints[access_hint_on_compaction_start]);
Log(log," Options.use_adaptive_mutex: %d",
use_adaptive_mutex);
} // Options::Dump
//