Add lock wait time as a perf context counter

Summary:
Adds two new counters:

`key_lock_wait_count` counts how many times a lock was blocked by another transaction and had to wait, instead of being granted the lock immediately.
`key_lock_wait_time` counts the time spent acquiring locks.
Closes https://github.com/facebook/rocksdb/pull/3107

Differential Revision: D6217332

Pulled By: lth

fbshipit-source-id: 55d4f46da5550c333e523263422fd61d6a46deb9
This commit is contained in:
Manuel Ung 2017-11-06 10:52:17 -08:00 committed by Facebook Github Bot
parent be410dede8
commit e03377c7fd
4 changed files with 18 additions and 0 deletions

View File

@ -131,6 +131,11 @@ struct PerfContext {
// total number of SST table bloom misses // total number of SST table bloom misses
uint64_t bloom_sst_miss_count; uint64_t bloom_sst_miss_count;
// Time spent waiting on key locks in transaction lock manager.
uint64_t key_lock_wait_time;
// number of times acquiring a lock was blocked by another transaction.
uint64_t key_lock_wait_count;
// Total time spent in Env filesystem operations. These are only populated // Total time spent in Env filesystem operations. These are only populated
// when TimedEnv is used. // when TimedEnv is used.
uint64_t env_new_sequential_file_nanos; uint64_t env_new_sequential_file_nanos;

View File

@ -79,6 +79,8 @@ void PerfContext::Reset() {
bloom_memtable_miss_count = 0; bloom_memtable_miss_count = 0;
bloom_sst_hit_count = 0; bloom_sst_hit_count = 0;
bloom_sst_miss_count = 0; bloom_sst_miss_count = 0;
key_lock_wait_time = 0;
key_lock_wait_count = 0;
env_new_sequential_file_nanos = 0; env_new_sequential_file_nanos = 0;
env_new_random_access_file_nanos = 0; env_new_random_access_file_nanos = 0;
@ -158,6 +160,8 @@ std::string PerfContext::ToString(bool exclude_zero_counters) const {
PERF_CONTEXT_OUTPUT(bloom_memtable_miss_count); PERF_CONTEXT_OUTPUT(bloom_memtable_miss_count);
PERF_CONTEXT_OUTPUT(bloom_sst_hit_count); PERF_CONTEXT_OUTPUT(bloom_sst_hit_count);
PERF_CONTEXT_OUTPUT(bloom_sst_miss_count); PERF_CONTEXT_OUTPUT(bloom_sst_miss_count);
PERF_CONTEXT_OUTPUT(key_lock_wait_time);
PERF_CONTEXT_OUTPUT(key_lock_wait_count);
PERF_CONTEXT_OUTPUT(env_new_sequential_file_nanos); PERF_CONTEXT_OUTPUT(env_new_sequential_file_nanos);
PERF_CONTEXT_OUTPUT(env_new_random_access_file_nanos); PERF_CONTEXT_OUTPUT(env_new_random_access_file_nanos);
PERF_CONTEXT_OUTPUT(env_new_writable_file_nanos); PERF_CONTEXT_OUTPUT(env_new_writable_file_nanos);

View File

@ -20,6 +20,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "monitoring/perf_context_imp.h"
#include "rocksdb/slice.h" #include "rocksdb/slice.h"
#include "rocksdb/utilities/transaction_db_mutex.h" #include "rocksdb/utilities/transaction_db_mutex.h"
#include "util/cast_util.h" #include "util/cast_util.h"
@ -347,6 +348,8 @@ Status TransactionLockMgr::AcquireWithTimeout(
&expire_time_hint, &wait_ids); &expire_time_hint, &wait_ids);
if (!result.ok() && timeout != 0) { if (!result.ok() && timeout != 0) {
PERF_TIMER_GUARD(key_lock_wait_time);
PERF_COUNTER_ADD(key_lock_wait_count, 1);
// If we weren't able to acquire the lock, we will keep retrying as long // If we weren't able to acquire the lock, we will keep retrying as long
// as the timeout allows. // as the timeout allows.
bool timed_out = false; bool timed_out = false;

View File

@ -19,6 +19,7 @@
#include "db/db_impl.h" #include "db/db_impl.h"
#include "rocksdb/db.h" #include "rocksdb/db.h"
#include "rocksdb/options.h" #include "rocksdb/options.h"
#include "rocksdb/perf_context.h"
#include "rocksdb/utilities/transaction.h" #include "rocksdb/utilities/transaction.h"
#include "rocksdb/utilities/transaction_db.h" #include "rocksdb/utilities/transaction_db.h"
#include "table/mock_table.h" #include "table/mock_table.h"
@ -187,15 +188,18 @@ TEST_P(TransactionTest, WaitingTxn) {
ASSERT_EQ(cf_id, 0); ASSERT_EQ(cf_id, 0);
}); });
get_perf_context()->Reset();
// lock key in default cf // lock key in default cf
s = txn1->GetForUpdate(read_options, "foo", &value); s = txn1->GetForUpdate(read_options, "foo", &value);
ASSERT_OK(s); ASSERT_OK(s);
ASSERT_EQ(value, "bar"); ASSERT_EQ(value, "bar");
ASSERT_EQ(get_perf_context()->key_lock_wait_count, 0);
// lock key in cfa // lock key in cfa
s = txn1->GetForUpdate(read_options, cfa, "foo", &value); s = txn1->GetForUpdate(read_options, cfa, "foo", &value);
ASSERT_OK(s); ASSERT_OK(s);
ASSERT_EQ(value, "bar"); ASSERT_EQ(value, "bar");
ASSERT_EQ(get_perf_context()->key_lock_wait_count, 0);
auto lock_data = db->GetLockStatusData(); auto lock_data = db->GetLockStatusData();
// Locked keys exist in both column family. // Locked keys exist in both column family.
@ -231,6 +235,8 @@ TEST_P(TransactionTest, WaitingTxn) {
s = txn2->GetForUpdate(read_options, "foo", &value); s = txn2->GetForUpdate(read_options, "foo", &value);
ASSERT_TRUE(s.IsTimedOut()); ASSERT_TRUE(s.IsTimedOut());
ASSERT_EQ(s.ToString(), "Operation timed out: Timeout waiting to lock key"); ASSERT_EQ(s.ToString(), "Operation timed out: Timeout waiting to lock key");
ASSERT_EQ(get_perf_context()->key_lock_wait_count, 1);
ASSERT_GE(get_perf_context()->key_lock_wait_time, 0);
rocksdb::SyncPoint::GetInstance()->DisableProcessing(); rocksdb::SyncPoint::GetInstance()->DisableProcessing();
rocksdb::SyncPoint::GetInstance()->ClearAllCallBacks(); rocksdb::SyncPoint::GetInstance()->ClearAllCallBacks();