[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
main
Haobo Xu 12 years ago
parent ab8d2f6ab2
commit d897d33bf1
  1. 10
      db/db_bench.cc
  2. 1
      db/db_impl.cc
  3. 8
      include/leveldb/options.h
  4. 19
      port/port_posix.cc
  5. 2
      port/port_posix.h
  6. 5
      util/options.cc

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

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

@ -451,6 +451,14 @@ struct Options {
// It will be applied to all input files of a compaction. // It will be applied to all input files of a compaction.
// Default: NORMAL // Default: NORMAL
enum { NONE, NORMAL, SEQUENTIAL, WILLNEED } access_hint_on_compaction_start; 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 // Options that control read operations

@ -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_)); } Mutex::~Mutex() { PthreadCall("destroy mutex", pthread_mutex_destroy(&mu_)); }

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

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

Loading…
Cancel
Save