diff --git a/db/db_bench.cc b/db/db_bench.cc index abaa41507f..8a56f5d504 100644 --- a/db/db_bench.cc +++ b/db/db_bench.cc @@ -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 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); diff --git a/db/db_impl.cc b/db/db_impl.cc index 4aa797ce49..84bc1ed2fa 100644 --- a/db/db_impl.cc +++ b/db/db_impl.cc @@ -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())), diff --git a/include/leveldb/options.h b/include/leveldb/options.h index 5085e160e2..d25b26f900 100644 --- a/include/leveldb/options.h +++ b/include/leveldb/options.h @@ -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 diff --git a/port/port_posix.cc b/port/port_posix.cc index 82cecdf2c9..8e8efed441 100644 --- a/port/port_posix.cc +++ b/port/port_posix.cc @@ -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_)); } diff --git a/port/port_posix.h b/port/port_posix.h index e2540a4261..80adaf60a8 100644 --- a/port/port_posix.h +++ b/port/port_posix.h @@ -82,7 +82,7 @@ class CondVar; class Mutex { public: - Mutex(); + Mutex(bool adaptive = false); ~Mutex(); void Lock(); diff --git a/util/options.cc b/util/options.cc index 6f7731d8d8..022299caf4 100644 --- a/util/options.cc +++ b/util/options.cc @@ -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 //