Add a perf context level that doesn't measure time for mutex operations

Summary: Timing mutex operations can impact scalability of the system. Add a new perf context level that can measure time counters except for mutex.

Test Plan: Add a new unit test case to make sure it is not set.

Reviewers: IslamAbdelRahman, rven, kradhakrishnan, yhchiang, anthony

Reviewed By: anthony

Subscribers: MarkCallaghan, leveldb, dhruba

Differential Revision: https://reviews.facebook.net/D53199
This commit is contained in:
sdong 2016-01-21 13:55:56 -08:00
parent f7ef1a6132
commit fb9811ee9b
6 changed files with 34 additions and 25 deletions

View File

@ -1,5 +1,9 @@
# Rocksdb Change Log # Rocksdb Change Log
## Unreleased
### Public API Changes
* Add a new perf context level between kEnableCount and kEnableTime. Level 2 now doesn't include timers for mutexes.
## 4.4.0 (1/14/2016) ## 4.4.0 (1/14/2016)
### Public API Changes ### Public API Changes
* Change names in CompactionPri and add a new one. * Change names in CompactionPri and add a new one.

View File

@ -543,28 +543,31 @@ TEST_F(PerfContextTest, SeekKeyComparison) {
} }
TEST_F(PerfContextTest, DBMutexLockCounter) { TEST_F(PerfContextTest, DBMutexLockCounter) {
SetPerfLevel(kEnableTime);
int stats_code[] = {0, static_cast<int>(DB_MUTEX_WAIT_MICROS)}; int stats_code[] = {0, static_cast<int>(DB_MUTEX_WAIT_MICROS)};
for (int c = 0; c < 2; ++c) { for (PerfLevel perf_level :
{PerfLevel::kEnableTimeExceptForMutex, PerfLevel::kEnableTime}) {
for (int c = 0; c < 2; ++c) {
InstrumentedMutex mutex(nullptr, Env::Default(), stats_code[c]); InstrumentedMutex mutex(nullptr, Env::Default(), stats_code[c]);
mutex.Lock(); mutex.Lock();
std::thread child_thread([&] { std::thread child_thread([&] {
SetPerfLevel(kEnableTime); SetPerfLevel(perf_level);
perf_context.Reset(); perf_context.Reset();
ASSERT_EQ(perf_context.db_mutex_lock_nanos, 0); ASSERT_EQ(perf_context.db_mutex_lock_nanos, 0);
mutex.Lock(); mutex.Lock();
mutex.Unlock(); mutex.Unlock();
if (stats_code[c] == DB_MUTEX_WAIT_MICROS) { if (perf_level == PerfLevel::kEnableTimeExceptForMutex ||
stats_code[c] != DB_MUTEX_WAIT_MICROS) {
ASSERT_EQ(perf_context.db_mutex_lock_nanos, 0);
} else {
// increment the counter only when it's a DB Mutex // increment the counter only when it's a DB Mutex
ASSERT_GT(perf_context.db_mutex_lock_nanos, 0); ASSERT_GT(perf_context.db_mutex_lock_nanos, 0);
} else {
ASSERT_EQ(perf_context.db_mutex_lock_nanos, 0);
} }
}); });
Env::Default()->SleepForMicroseconds(100); Env::Default()->SleepForMicroseconds(100);
mutex.Unlock(); mutex.Unlock();
child_thread.join(); child_thread.join();
} }
}
} }
TEST_F(PerfContextTest, FalseDBMutexWait) { TEST_F(PerfContextTest, FalseDBMutexWait) {

View File

@ -14,9 +14,11 @@ namespace rocksdb {
// How much perf stats to collect. Affects perf_context and iostats_context. // How much perf stats to collect. Affects perf_context and iostats_context.
enum PerfLevel { enum PerfLevel {
kDisable = 0, // disable perf stats kDisable = 0, // disable perf stats
kEnableCount = 1, // enable only count stats kEnableCount = 1, // enable only count stats
kEnableTime = 2 // enable time stats too kEnableTimeExceptForMutex = 2, // Other than count stats, also enable time
// stats except for mutexes
kEnableTime = 3 // enable count and time stats
}; };
// set the perf stats level for current thread // set the perf stats level for current thread

View File

@ -9,8 +9,8 @@
namespace rocksdb { namespace rocksdb {
void InstrumentedMutex::Lock() { void InstrumentedMutex::Lock() {
PERF_CONDITIONAL_TIMER_GUARD(db_mutex_lock_nanos, PERF_CONDITIONAL_TIMER_FOR_MUTEX_GUARD(db_mutex_lock_nanos,
stats_code_ == DB_MUTEX_WAIT_MICROS); stats_code_ == DB_MUTEX_WAIT_MICROS);
uint64_t wait_time_micros = 0; uint64_t wait_time_micros = 0;
if (env_ != nullptr && stats_ != nullptr) { if (env_ != nullptr && stats_ != nullptr) {
{ {
@ -31,8 +31,8 @@ void InstrumentedMutex::LockInternal() {
} }
void InstrumentedCondVar::Wait() { void InstrumentedCondVar::Wait() {
PERF_CONDITIONAL_TIMER_GUARD(db_condition_wait_nanos, PERF_CONDITIONAL_TIMER_FOR_MUTEX_GUARD(db_condition_wait_nanos,
stats_code_ == DB_MUTEX_WAIT_MICROS); stats_code_ == DB_MUTEX_WAIT_MICROS);
uint64_t wait_time_micros = 0; uint64_t wait_time_micros = 0;
if (env_ != nullptr && stats_ != nullptr) { if (env_ != nullptr && stats_ != nullptr) {
{ {
@ -53,8 +53,8 @@ void InstrumentedCondVar::WaitInternal() {
} }
bool InstrumentedCondVar::TimedWait(uint64_t abs_time_us) { bool InstrumentedCondVar::TimedWait(uint64_t abs_time_us) {
PERF_CONDITIONAL_TIMER_GUARD(db_condition_wait_nanos, PERF_CONDITIONAL_TIMER_FOR_MUTEX_GUARD(db_condition_wait_nanos,
stats_code_ == DB_MUTEX_WAIT_MICROS); stats_code_ == DB_MUTEX_WAIT_MICROS);
uint64_t wait_time_micros = 0; uint64_t wait_time_micros = 0;
bool result = false; bool result = false;
if (env_ != nullptr && stats_ != nullptr) { if (env_ != nullptr && stats_ != nullptr) {

View File

@ -33,10 +33,10 @@ namespace rocksdb {
PerfStepTimer perf_step_timer_ ## metric(&(perf_context.metric)); \ PerfStepTimer perf_step_timer_ ## metric(&(perf_context.metric)); \
perf_step_timer_ ## metric.Start(); perf_step_timer_ ## metric.Start();
#define PERF_CONDITIONAL_TIMER_GUARD(metric, condition) \ #define PERF_CONDITIONAL_TIMER_FOR_MUTEX_GUARD(metric, condition) \
PerfStepTimer perf_step_timer_##metric(&(perf_context.metric)); \ PerfStepTimer perf_step_timer_##metric(&(perf_context.metric), true); \
if ((condition)) { \ if ((condition)) { \
perf_step_timer_##metric.Start(); \ perf_step_timer_##metric.Start(); \
} }
// Update metric with time elapsed since last START. start time is reset // Update metric with time elapsed since last START. start time is reset

View File

@ -12,12 +12,12 @@ namespace rocksdb {
class PerfStepTimer { class PerfStepTimer {
public: public:
PerfStepTimer(uint64_t* metric) explicit PerfStepTimer(uint64_t* metric, bool for_mutex = false)
: enabled_(perf_level >= PerfLevel::kEnableTime), : enabled_(perf_level >= PerfLevel::kEnableTime ||
env_(enabled_ ? Env::Default() : nullptr), (!for_mutex && perf_level >= kEnableTimeExceptForMutex)),
start_(0), env_(enabled_ ? Env::Default() : nullptr),
metric_(metric) { start_(0),
} metric_(metric) {}
~PerfStepTimer() { ~PerfStepTimer() {
Stop(); Stop();