using ThreadLocalPtr to hide ROCKSDB_SUPPORT_THREAD_LOCAL from public…
Summary: … headers https://github.com/facebook/rocksdb/pull/2199 should not reference RocksDB-specific macros (like ROCKSDB_SUPPORT_THREAD_LOCAL in this case) to public headers, `iostats_context.h` and `perf_context.h`. We shouldn't do that because users have to provide these compiler flags when building their binary with RocksDB. We should hide the thread local global variable inside our implementation and just expose a function api to retrieve these variables. It may break some users for now but good for long term. make check -j64 Closes https://github.com/facebook/rocksdb/pull/2380 Differential Revision: D5177896 Pulled By: lightmark fbshipit-source-id: 6fcdfac57f2e2dcfe60992b7385c5403f6dcb390
This commit is contained in:
parent
138b87eae4
commit
7f6c02dda1
@ -4,6 +4,7 @@
|
||||
* Scheduling flushes and compactions in the same thread pool is no longer supported by setting `max_background_flushes=0`. Instead, users can achieve this by configuring their high-pri thread pool to have zero threads.
|
||||
* Replace `Options::max_background_flushes`, `Options::max_background_compactions`, and `Options::base_background_compactions` all with `Options::max_background_jobs`, which automatically decides how many threads to allocate towards flush/compaction.
|
||||
* options.delayed_write_rate by default take the value of options.rate_limiter rate.
|
||||
* Replace global variable `IOStatsContext iostats_context` with `IOStatsContext* get_iostats_context()`; replace global variable `PerfContext perf_context` with `PerfContext* get_perf_context()`.
|
||||
|
||||
### New Features
|
||||
* Change ticker/histogram statistics implementations to use core-local storage. This improves aggregation speed compared to our previous thread-local approach, particularly for applications with many threads.
|
||||
|
@ -366,9 +366,9 @@ TEST_F(DBBasicTest, FLUSH) {
|
||||
ASSERT_OK(Flush(1));
|
||||
ASSERT_OK(dbfull()->Put(writeOpt, handles_[1], "bar", "v1"));
|
||||
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
Get(1, "foo");
|
||||
ASSERT_TRUE((int)perf_context.get_from_output_files_time > 0);
|
||||
ASSERT_TRUE((int)get_perf_context()->get_from_output_files_time > 0);
|
||||
|
||||
ReopenWithColumnFamilies({"default", "pikachu"}, CurrentOptions());
|
||||
ASSERT_EQ("v1", Get(1, "foo"));
|
||||
@ -381,9 +381,9 @@ TEST_F(DBBasicTest, FLUSH) {
|
||||
|
||||
ReopenWithColumnFamilies({"default", "pikachu"}, CurrentOptions());
|
||||
ASSERT_EQ("v2", Get(1, "bar"));
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
ASSERT_EQ("v2", Get(1, "foo"));
|
||||
ASSERT_TRUE((int)perf_context.get_from_output_files_time > 0);
|
||||
ASSERT_TRUE((int)get_perf_context()->get_from_output_files_time > 0);
|
||||
|
||||
writeOpt.disableWAL = false;
|
||||
ASSERT_OK(dbfull()->Put(writeOpt, handles_[1], "bar", "v3"));
|
||||
|
@ -688,12 +688,12 @@ class BloomStatsTestWithParam
|
||||
}
|
||||
options_.env = env_;
|
||||
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
DestroyAndReopen(options_);
|
||||
}
|
||||
|
||||
~BloomStatsTestWithParam() {
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
Destroy(options_);
|
||||
}
|
||||
|
||||
@ -726,33 +726,33 @@ TEST_P(BloomStatsTestWithParam, BloomStatsTest) {
|
||||
|
||||
// check memtable bloom stats
|
||||
ASSERT_EQ(value1, Get(key1));
|
||||
ASSERT_EQ(1, perf_context.bloom_memtable_hit_count);
|
||||
ASSERT_EQ(1, get_perf_context()->bloom_memtable_hit_count);
|
||||
ASSERT_EQ(value3, Get(key3));
|
||||
ASSERT_EQ(2, perf_context.bloom_memtable_hit_count);
|
||||
ASSERT_EQ(0, perf_context.bloom_memtable_miss_count);
|
||||
ASSERT_EQ(2, get_perf_context()->bloom_memtable_hit_count);
|
||||
ASSERT_EQ(0, get_perf_context()->bloom_memtable_miss_count);
|
||||
|
||||
ASSERT_EQ("NOT_FOUND", Get(key2));
|
||||
ASSERT_EQ(1, perf_context.bloom_memtable_miss_count);
|
||||
ASSERT_EQ(2, perf_context.bloom_memtable_hit_count);
|
||||
ASSERT_EQ(1, get_perf_context()->bloom_memtable_miss_count);
|
||||
ASSERT_EQ(2, get_perf_context()->bloom_memtable_hit_count);
|
||||
|
||||
// sanity checks
|
||||
ASSERT_EQ(0, perf_context.bloom_sst_hit_count);
|
||||
ASSERT_EQ(0, perf_context.bloom_sst_miss_count);
|
||||
ASSERT_EQ(0, get_perf_context()->bloom_sst_hit_count);
|
||||
ASSERT_EQ(0, get_perf_context()->bloom_sst_miss_count);
|
||||
|
||||
Flush();
|
||||
|
||||
// sanity checks
|
||||
ASSERT_EQ(0, perf_context.bloom_sst_hit_count);
|
||||
ASSERT_EQ(0, perf_context.bloom_sst_miss_count);
|
||||
ASSERT_EQ(0, get_perf_context()->bloom_sst_hit_count);
|
||||
ASSERT_EQ(0, get_perf_context()->bloom_sst_miss_count);
|
||||
|
||||
// check SST bloom stats
|
||||
ASSERT_EQ(value1, Get(key1));
|
||||
ASSERT_EQ(1, perf_context.bloom_sst_hit_count);
|
||||
ASSERT_EQ(1, get_perf_context()->bloom_sst_hit_count);
|
||||
ASSERT_EQ(value3, Get(key3));
|
||||
ASSERT_EQ(2, perf_context.bloom_sst_hit_count);
|
||||
ASSERT_EQ(2, get_perf_context()->bloom_sst_hit_count);
|
||||
|
||||
ASSERT_EQ("NOT_FOUND", Get(key2));
|
||||
ASSERT_EQ(1, perf_context.bloom_sst_miss_count);
|
||||
ASSERT_EQ(1, get_perf_context()->bloom_sst_miss_count);
|
||||
}
|
||||
|
||||
// Same scenario as in BloomStatsTest but using an iterator
|
||||
@ -773,21 +773,21 @@ TEST_P(BloomStatsTestWithParam, BloomStatsTestWithIter) {
|
||||
ASSERT_OK(iter->status());
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(value1, iter->value().ToString());
|
||||
ASSERT_EQ(1, perf_context.bloom_memtable_hit_count);
|
||||
ASSERT_EQ(0, perf_context.bloom_memtable_miss_count);
|
||||
ASSERT_EQ(1, get_perf_context()->bloom_memtable_hit_count);
|
||||
ASSERT_EQ(0, get_perf_context()->bloom_memtable_miss_count);
|
||||
|
||||
iter->Seek(key3);
|
||||
ASSERT_OK(iter->status());
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(value3, iter->value().ToString());
|
||||
ASSERT_EQ(2, perf_context.bloom_memtable_hit_count);
|
||||
ASSERT_EQ(0, perf_context.bloom_memtable_miss_count);
|
||||
ASSERT_EQ(2, get_perf_context()->bloom_memtable_hit_count);
|
||||
ASSERT_EQ(0, get_perf_context()->bloom_memtable_miss_count);
|
||||
|
||||
iter->Seek(key2);
|
||||
ASSERT_OK(iter->status());
|
||||
ASSERT_TRUE(!iter->Valid());
|
||||
ASSERT_EQ(1, perf_context.bloom_memtable_miss_count);
|
||||
ASSERT_EQ(2, perf_context.bloom_memtable_hit_count);
|
||||
ASSERT_EQ(1, get_perf_context()->bloom_memtable_miss_count);
|
||||
ASSERT_EQ(2, get_perf_context()->bloom_memtable_hit_count);
|
||||
|
||||
Flush();
|
||||
|
||||
@ -798,19 +798,19 @@ TEST_P(BloomStatsTestWithParam, BloomStatsTestWithIter) {
|
||||
ASSERT_OK(iter->status());
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(value1, iter->value().ToString());
|
||||
ASSERT_EQ(1, perf_context.bloom_sst_hit_count);
|
||||
ASSERT_EQ(1, get_perf_context()->bloom_sst_hit_count);
|
||||
|
||||
iter->Seek(key3);
|
||||
ASSERT_OK(iter->status());
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(value3, iter->value().ToString());
|
||||
ASSERT_EQ(2, perf_context.bloom_sst_hit_count);
|
||||
ASSERT_EQ(2, get_perf_context()->bloom_sst_hit_count);
|
||||
|
||||
iter->Seek(key2);
|
||||
ASSERT_OK(iter->status());
|
||||
ASSERT_TRUE(!iter->Valid());
|
||||
ASSERT_EQ(1, perf_context.bloom_sst_miss_count);
|
||||
ASSERT_EQ(2, perf_context.bloom_sst_hit_count);
|
||||
ASSERT_EQ(1, get_perf_context()->bloom_sst_miss_count);
|
||||
ASSERT_EQ(2, get_perf_context()->bloom_sst_hit_count);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(BloomStatsTestWithParam, BloomStatsTestWithParam,
|
||||
|
@ -354,11 +354,11 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
SetPerfLevel(kEnableCount);
|
||||
ASSERT_TRUE(GetPerfLevel() == kEnableCount);
|
||||
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
db_iter->SeekToLast();
|
||||
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(static_cast<int>(perf_context.internal_key_skipped_count), 7);
|
||||
ASSERT_EQ(static_cast<int>(get_perf_context()->internal_key_skipped_count), 7);
|
||||
ASSERT_EQ(db_iter->key().ToString(), "b");
|
||||
|
||||
SetPerfLevel(kDisable);
|
||||
@ -473,11 +473,11 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
SetPerfLevel(kEnableCount);
|
||||
ASSERT_TRUE(GetPerfLevel() == kEnableCount);
|
||||
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
db_iter->SeekToLast();
|
||||
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(static_cast<int>(perf_context.internal_delete_skipped_count), 1);
|
||||
ASSERT_EQ(static_cast<int>(get_perf_context()->internal_delete_skipped_count), 1);
|
||||
ASSERT_EQ(db_iter->key().ToString(), "b");
|
||||
|
||||
SetPerfLevel(kDisable);
|
||||
|
@ -974,11 +974,11 @@ TEST_F(DBIteratorTest, DBIteratorBoundTest) {
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(iter->key().compare(("b1")), 0);
|
||||
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
iter->Next();
|
||||
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(static_cast<int>(perf_context.internal_delete_skipped_count), 2);
|
||||
ASSERT_EQ(static_cast<int>(get_perf_context()->internal_delete_skipped_count), 2);
|
||||
|
||||
// now testing with iterate_bound
|
||||
Slice prefix("c");
|
||||
@ -986,7 +986,7 @@ TEST_F(DBIteratorTest, DBIteratorBoundTest) {
|
||||
|
||||
iter.reset(db_->NewIterator(ro));
|
||||
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
|
||||
iter->Seek("b");
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
@ -1001,7 +1001,7 @@ TEST_F(DBIteratorTest, DBIteratorBoundTest) {
|
||||
// even though the key is deleted
|
||||
// hence internal_delete_skipped_count should be 0
|
||||
ASSERT_TRUE(!iter->Valid());
|
||||
ASSERT_EQ(static_cast<int>(perf_context.internal_delete_skipped_count), 0);
|
||||
ASSERT_EQ(static_cast<int>(get_perf_context()->internal_delete_skipped_count), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1888,7 +1888,7 @@ TEST_F(DBIteratorTest, DBIteratorSkipRecentDuplicatesTest) {
|
||||
#endif
|
||||
|
||||
// Seek iterator to a smaller key.
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
iter->Seek("a");
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
EXPECT_EQ("b", iter->key().ToString());
|
||||
@ -1896,17 +1896,17 @@ TEST_F(DBIteratorTest, DBIteratorSkipRecentDuplicatesTest) {
|
||||
|
||||
// Check that the seek didn't do too much work.
|
||||
// Checks are not tight, just make sure that everything is well below 100.
|
||||
EXPECT_LT(perf_context.internal_key_skipped_count, 4);
|
||||
EXPECT_LT(perf_context.internal_recent_skipped_count, 8);
|
||||
EXPECT_LT(perf_context.seek_on_memtable_count, 10);
|
||||
EXPECT_LT(perf_context.next_on_memtable_count, 10);
|
||||
EXPECT_LT(perf_context.prev_on_memtable_count, 10);
|
||||
EXPECT_LT(get_perf_context()->internal_key_skipped_count, 4);
|
||||
EXPECT_LT(get_perf_context()->internal_recent_skipped_count, 8);
|
||||
EXPECT_LT(get_perf_context()->seek_on_memtable_count, 10);
|
||||
EXPECT_LT(get_perf_context()->next_on_memtable_count, 10);
|
||||
EXPECT_LT(get_perf_context()->prev_on_memtable_count, 10);
|
||||
|
||||
// Check that iterator did something like what we expect.
|
||||
EXPECT_EQ(perf_context.internal_delete_skipped_count, 0);
|
||||
EXPECT_EQ(perf_context.internal_merge_count, 0);
|
||||
EXPECT_GE(perf_context.internal_recent_skipped_count, 2);
|
||||
EXPECT_GE(perf_context.seek_on_memtable_count, 2);
|
||||
EXPECT_EQ(get_perf_context()->internal_delete_skipped_count, 0);
|
||||
EXPECT_EQ(get_perf_context()->internal_merge_count, 0);
|
||||
EXPECT_GE(get_perf_context()->internal_recent_skipped_count, 2);
|
||||
EXPECT_GE(get_perf_context()->seek_on_memtable_count, 2);
|
||||
EXPECT_EQ(1, options.statistics->getTickerCount(
|
||||
NUMBER_OF_RESEEKS_IN_ITERATION));
|
||||
}
|
||||
|
@ -533,9 +533,9 @@ TEST_F(DBPropertiesTest, NumImmutableMemTable) {
|
||||
ASSERT_TRUE(dbfull()->GetProperty(
|
||||
handles_[1], "rocksdb.num-entries-active-mem-table", &num));
|
||||
ASSERT_EQ(num, "1");
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
Get(1, "k1");
|
||||
ASSERT_EQ(1, static_cast<int>(perf_context.get_from_memtable_count));
|
||||
ASSERT_EQ(1, static_cast<int>(get_perf_context()->get_from_memtable_count));
|
||||
|
||||
ASSERT_OK(dbfull()->Put(writeOpt, handles_[1], "k2", big_value));
|
||||
ASSERT_TRUE(dbfull()->GetProperty(handles_[1],
|
||||
@ -548,12 +548,12 @@ TEST_F(DBPropertiesTest, NumImmutableMemTable) {
|
||||
handles_[1], "rocksdb.num-entries-imm-mem-tables", &num));
|
||||
ASSERT_EQ(num, "1");
|
||||
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
Get(1, "k1");
|
||||
ASSERT_EQ(2, static_cast<int>(perf_context.get_from_memtable_count));
|
||||
perf_context.Reset();
|
||||
ASSERT_EQ(2, static_cast<int>(get_perf_context()->get_from_memtable_count));
|
||||
get_perf_context()->Reset();
|
||||
Get(1, "k2");
|
||||
ASSERT_EQ(1, static_cast<int>(perf_context.get_from_memtable_count));
|
||||
ASSERT_EQ(1, static_cast<int>(get_perf_context()->get_from_memtable_count));
|
||||
|
||||
ASSERT_OK(dbfull()->Put(writeOpt, handles_[1], "k3", big_value));
|
||||
ASSERT_TRUE(dbfull()->GetProperty(
|
||||
@ -567,15 +567,15 @@ TEST_F(DBPropertiesTest, NumImmutableMemTable) {
|
||||
ASSERT_TRUE(dbfull()->GetProperty(
|
||||
handles_[1], "rocksdb.num-entries-imm-mem-tables", &num));
|
||||
ASSERT_EQ(num, "2");
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
Get(1, "k2");
|
||||
ASSERT_EQ(2, static_cast<int>(perf_context.get_from_memtable_count));
|
||||
perf_context.Reset();
|
||||
ASSERT_EQ(2, static_cast<int>(get_perf_context()->get_from_memtable_count));
|
||||
get_perf_context()->Reset();
|
||||
Get(1, "k3");
|
||||
ASSERT_EQ(1, static_cast<int>(perf_context.get_from_memtable_count));
|
||||
perf_context.Reset();
|
||||
ASSERT_EQ(1, static_cast<int>(get_perf_context()->get_from_memtable_count));
|
||||
get_perf_context()->Reset();
|
||||
Get(1, "k1");
|
||||
ASSERT_EQ(3, static_cast<int>(perf_context.get_from_memtable_count));
|
||||
ASSERT_EQ(3, static_cast<int>(get_perf_context()->get_from_memtable_count));
|
||||
|
||||
ASSERT_OK(Flush(1));
|
||||
ASSERT_TRUE(dbfull()->GetProperty(handles_[1],
|
||||
@ -670,7 +670,7 @@ TEST_F(DBPropertiesTest, DISABLED_GetProperty) {
|
||||
ASSERT_EQ(num, "0");
|
||||
ASSERT_TRUE(dbfull()->GetProperty("rocksdb.estimate-num-keys", &num));
|
||||
ASSERT_EQ(num, "1");
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
|
||||
ASSERT_OK(dbfull()->Put(writeOpt, "k2", big_value));
|
||||
ASSERT_TRUE(dbfull()->GetProperty("rocksdb.num-immutable-mem-table", &num));
|
||||
@ -1228,7 +1228,7 @@ TEST_F(DBPropertiesTest, TablePropertiesNeedCompactTest) {
|
||||
|
||||
{
|
||||
SetPerfLevel(kEnableCount);
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
int c = 0;
|
||||
std::unique_ptr<Iterator> iter(db_->NewIterator(ReadOptions()));
|
||||
iter->Seek(Key(kMaxKey - 100));
|
||||
@ -1236,8 +1236,8 @@ TEST_F(DBPropertiesTest, TablePropertiesNeedCompactTest) {
|
||||
iter->Next();
|
||||
}
|
||||
ASSERT_EQ(c, 0);
|
||||
ASSERT_LT(perf_context.internal_delete_skipped_count, 30u);
|
||||
ASSERT_LT(perf_context.internal_key_skipped_count, 30u);
|
||||
ASSERT_LT(get_perf_context()->internal_delete_skipped_count, 30u);
|
||||
ASSERT_LT(get_perf_context()->internal_key_skipped_count, 30u);
|
||||
SetPerfLevel(kDisable);
|
||||
}
|
||||
}
|
||||
@ -1284,16 +1284,16 @@ TEST_F(DBPropertiesTest, NeedCompactHintPersistentTest) {
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 0);
|
||||
{
|
||||
SetPerfLevel(kEnableCount);
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
int c = 0;
|
||||
std::unique_ptr<Iterator> iter(db_->NewIterator(ReadOptions()));
|
||||
for (iter->Seek(Key(0)); iter->Valid(); iter->Next()) {
|
||||
c++;
|
||||
}
|
||||
ASSERT_EQ(c, 2);
|
||||
ASSERT_EQ(perf_context.internal_delete_skipped_count, 0);
|
||||
ASSERT_EQ(get_perf_context()->internal_delete_skipped_count, 0);
|
||||
// We iterate every key twice. Is it a bug?
|
||||
ASSERT_LE(perf_context.internal_key_skipped_count, 2);
|
||||
ASSERT_LE(get_perf_context()->internal_key_skipped_count, 2);
|
||||
SetPerfLevel(kDisable);
|
||||
}
|
||||
}
|
||||
|
@ -89,13 +89,13 @@ TEST_F(PerfContextTest, SeekIntoDeletion) {
|
||||
std::string key = "k" + ToString(i);
|
||||
std::string value;
|
||||
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
StopWatchNano timer(Env::Default());
|
||||
timer.Start();
|
||||
auto status = db->Get(read_options, key, &value);
|
||||
auto elapsed_nanos = timer.ElapsedNanos();
|
||||
ASSERT_TRUE(status.IsNotFound());
|
||||
hist_get.Add(perf_context.user_key_comparison_count);
|
||||
hist_get.Add(get_perf_context()->user_key_comparison_count);
|
||||
hist_get_time.Add(elapsed_nanos);
|
||||
}
|
||||
|
||||
@ -108,19 +108,19 @@ TEST_F(PerfContextTest, SeekIntoDeletion) {
|
||||
HistogramImpl hist_seek_to_first;
|
||||
std::unique_ptr<Iterator> iter(db->NewIterator(read_options));
|
||||
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
StopWatchNano timer(Env::Default(), true);
|
||||
iter->SeekToFirst();
|
||||
hist_seek_to_first.Add(perf_context.user_key_comparison_count);
|
||||
hist_seek_to_first.Add(get_perf_context()->user_key_comparison_count);
|
||||
auto elapsed_nanos = timer.ElapsedNanos();
|
||||
|
||||
if (FLAGS_verbose) {
|
||||
std::cout << "SeekToFirst uesr key comparison: \n"
|
||||
<< hist_seek_to_first.ToString()
|
||||
<< "ikey skipped: " << perf_context.internal_key_skipped_count
|
||||
<< "ikey skipped: " << get_perf_context()->internal_key_skipped_count
|
||||
<< "\n"
|
||||
<< "idelete skipped: "
|
||||
<< perf_context.internal_delete_skipped_count << "\n"
|
||||
<< get_perf_context()->internal_delete_skipped_count << "\n"
|
||||
<< "elapsed: " << elapsed_nanos << "\n";
|
||||
}
|
||||
}
|
||||
@ -130,26 +130,26 @@ TEST_F(PerfContextTest, SeekIntoDeletion) {
|
||||
std::unique_ptr<Iterator> iter(db->NewIterator(read_options));
|
||||
std::string key = "k" + ToString(i);
|
||||
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
StopWatchNano timer(Env::Default(), true);
|
||||
iter->Seek(key);
|
||||
auto elapsed_nanos = timer.ElapsedNanos();
|
||||
hist_seek.Add(perf_context.user_key_comparison_count);
|
||||
hist_seek.Add(get_perf_context()->user_key_comparison_count);
|
||||
if (FLAGS_verbose) {
|
||||
std::cout << "seek cmp: " << perf_context.user_key_comparison_count
|
||||
<< " ikey skipped " << perf_context.internal_key_skipped_count
|
||||
std::cout << "seek cmp: " << get_perf_context()->user_key_comparison_count
|
||||
<< " ikey skipped " << get_perf_context()->internal_key_skipped_count
|
||||
<< " idelete skipped "
|
||||
<< perf_context.internal_delete_skipped_count
|
||||
<< get_perf_context()->internal_delete_skipped_count
|
||||
<< " elapsed: " << elapsed_nanos << "ns\n";
|
||||
}
|
||||
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
StopWatchNano timer2(Env::Default(), true);
|
||||
iter->Next();
|
||||
auto elapsed_nanos2 = timer2.ElapsedNanos();
|
||||
if (FLAGS_verbose) {
|
||||
std::cout << "next cmp: " << perf_context.user_key_comparison_count
|
||||
std::cout << "next cmp: " << get_perf_context()->user_key_comparison_count
|
||||
<< "elapsed: " << elapsed_nanos2 << "ns\n";
|
||||
}
|
||||
}
|
||||
@ -265,18 +265,18 @@ void ProfileQueries(bool enabled_time = false) {
|
||||
|
||||
std::vector<std::string> values;
|
||||
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
db->Put(write_options, key, value);
|
||||
if (++num_mutex_waited > 3) {
|
||||
#ifndef NDEBUG
|
||||
ThreadStatusUtil::TEST_SetStateDelay(ThreadStatus::STATE_MUTEX_WAIT, 0U);
|
||||
#endif
|
||||
}
|
||||
hist_write_pre_post.Add(perf_context.write_pre_and_post_process_time);
|
||||
hist_write_wal_time.Add(perf_context.write_wal_time);
|
||||
hist_write_memtable_time.Add(perf_context.write_memtable_time);
|
||||
hist_put.Add(perf_context.user_key_comparison_count);
|
||||
total_db_mutex_nanos += perf_context.db_mutex_lock_nanos;
|
||||
hist_write_pre_post.Add(get_perf_context()->write_pre_and_post_process_time);
|
||||
hist_write_wal_time.Add(get_perf_context()->write_wal_time);
|
||||
hist_write_memtable_time.Add(get_perf_context()->write_memtable_time);
|
||||
hist_put.Add(get_perf_context()->user_key_comparison_count);
|
||||
total_db_mutex_nanos += get_perf_context()->db_mutex_lock_nanos;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
ThreadStatusUtil::TEST_SetStateDelay(ThreadStatus::STATE_MUTEX_WAIT, 0U);
|
||||
@ -293,24 +293,24 @@ void ProfileQueries(bool enabled_time = false) {
|
||||
std::vector<Slice> multiget_keys = {Slice(key)};
|
||||
std::vector<std::string> values;
|
||||
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
ASSERT_OK(db->Get(read_options, key, &value));
|
||||
ASSERT_EQ(expected_value, value);
|
||||
hist_get_snapshot.Add(perf_context.get_snapshot_time);
|
||||
hist_get_memtable.Add(perf_context.get_from_memtable_time);
|
||||
hist_get_files.Add(perf_context.get_from_output_files_time);
|
||||
hist_num_memtable_checked.Add(perf_context.get_from_memtable_count);
|
||||
hist_get_post_process.Add(perf_context.get_post_process_time);
|
||||
hist_get.Add(perf_context.user_key_comparison_count);
|
||||
hist_get_snapshot.Add(get_perf_context()->get_snapshot_time);
|
||||
hist_get_memtable.Add(get_perf_context()->get_from_memtable_time);
|
||||
hist_get_files.Add(get_perf_context()->get_from_output_files_time);
|
||||
hist_num_memtable_checked.Add(get_perf_context()->get_from_memtable_count);
|
||||
hist_get_post_process.Add(get_perf_context()->get_post_process_time);
|
||||
hist_get.Add(get_perf_context()->user_key_comparison_count);
|
||||
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
db->MultiGet(read_options, multiget_keys, &values);
|
||||
hist_mget_snapshot.Add(perf_context.get_snapshot_time);
|
||||
hist_mget_memtable.Add(perf_context.get_from_memtable_time);
|
||||
hist_mget_files.Add(perf_context.get_from_output_files_time);
|
||||
hist_mget_num_memtable_checked.Add(perf_context.get_from_memtable_count);
|
||||
hist_mget_post_process.Add(perf_context.get_post_process_time);
|
||||
hist_mget.Add(perf_context.user_key_comparison_count);
|
||||
hist_mget_snapshot.Add(get_perf_context()->get_snapshot_time);
|
||||
hist_mget_memtable.Add(get_perf_context()->get_from_memtable_time);
|
||||
hist_mget_files.Add(get_perf_context()->get_from_output_files_time);
|
||||
hist_mget_num_memtable_checked.Add(get_perf_context()->get_from_memtable_count);
|
||||
hist_mget_post_process.Add(get_perf_context()->get_post_process_time);
|
||||
hist_mget.Add(get_perf_context()->user_key_comparison_count);
|
||||
}
|
||||
|
||||
if (FLAGS_verbose) {
|
||||
@ -394,24 +394,24 @@ void ProfileQueries(bool enabled_time = false) {
|
||||
std::vector<Slice> multiget_keys = {Slice(key)};
|
||||
std::vector<std::string> values;
|
||||
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
ASSERT_OK(db->Get(read_options, key, &value));
|
||||
ASSERT_EQ(expected_value, value);
|
||||
hist_get_snapshot.Add(perf_context.get_snapshot_time);
|
||||
hist_get_memtable.Add(perf_context.get_from_memtable_time);
|
||||
hist_get_files.Add(perf_context.get_from_output_files_time);
|
||||
hist_num_memtable_checked.Add(perf_context.get_from_memtable_count);
|
||||
hist_get_post_process.Add(perf_context.get_post_process_time);
|
||||
hist_get.Add(perf_context.user_key_comparison_count);
|
||||
hist_get_snapshot.Add(get_perf_context()->get_snapshot_time);
|
||||
hist_get_memtable.Add(get_perf_context()->get_from_memtable_time);
|
||||
hist_get_files.Add(get_perf_context()->get_from_output_files_time);
|
||||
hist_num_memtable_checked.Add(get_perf_context()->get_from_memtable_count);
|
||||
hist_get_post_process.Add(get_perf_context()->get_post_process_time);
|
||||
hist_get.Add(get_perf_context()->user_key_comparison_count);
|
||||
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
db->MultiGet(read_options, multiget_keys, &values);
|
||||
hist_mget_snapshot.Add(perf_context.get_snapshot_time);
|
||||
hist_mget_memtable.Add(perf_context.get_from_memtable_time);
|
||||
hist_mget_files.Add(perf_context.get_from_output_files_time);
|
||||
hist_mget_num_memtable_checked.Add(perf_context.get_from_memtable_count);
|
||||
hist_mget_post_process.Add(perf_context.get_post_process_time);
|
||||
hist_mget.Add(perf_context.user_key_comparison_count);
|
||||
hist_mget_snapshot.Add(get_perf_context()->get_snapshot_time);
|
||||
hist_mget_memtable.Add(get_perf_context()->get_from_memtable_time);
|
||||
hist_mget_files.Add(get_perf_context()->get_from_output_files_time);
|
||||
hist_mget_num_memtable_checked.Add(get_perf_context()->get_from_memtable_count);
|
||||
hist_mget_post_process.Add(get_perf_context()->get_post_process_time);
|
||||
hist_mget.Add(get_perf_context()->user_key_comparison_count);
|
||||
}
|
||||
|
||||
if (FLAGS_verbose) {
|
||||
@ -514,13 +514,13 @@ TEST_F(PerfContextTest, SeekKeyComparison) {
|
||||
std::string key = "k" + ToString(i);
|
||||
std::string value = "v" + ToString(i);
|
||||
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
timer.Start();
|
||||
db->Put(write_options, key, value);
|
||||
auto put_time = timer.ElapsedNanos();
|
||||
hist_put_time.Add(put_time);
|
||||
hist_wal_time.Add(perf_context.write_wal_time);
|
||||
hist_time_diff.Add(put_time - perf_context.write_wal_time);
|
||||
hist_wal_time.Add(get_perf_context()->write_wal_time);
|
||||
hist_time_diff.Add(put_time - get_perf_context()->write_wal_time);
|
||||
}
|
||||
|
||||
if (FLAGS_verbose) {
|
||||
@ -537,18 +537,18 @@ TEST_F(PerfContextTest, SeekKeyComparison) {
|
||||
std::string value = "v" + ToString(i);
|
||||
|
||||
std::unique_ptr<Iterator> iter(db->NewIterator(read_options));
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
iter->Seek(key);
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(iter->value().ToString(), value);
|
||||
hist_seek.Add(perf_context.user_key_comparison_count);
|
||||
hist_seek.Add(get_perf_context()->user_key_comparison_count);
|
||||
}
|
||||
|
||||
std::unique_ptr<Iterator> iter(db->NewIterator(read_options));
|
||||
for (iter->SeekToFirst(); iter->Valid();) {
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
iter->Next();
|
||||
hist_next.Add(perf_context.user_key_comparison_count);
|
||||
hist_next.Add(get_perf_context()->user_key_comparison_count);
|
||||
}
|
||||
|
||||
if (FLAGS_verbose) {
|
||||
@ -566,16 +566,16 @@ TEST_F(PerfContextTest, DBMutexLockCounter) {
|
||||
mutex.Lock();
|
||||
rocksdb::port::Thread child_thread([&] {
|
||||
SetPerfLevel(perf_level);
|
||||
perf_context.Reset();
|
||||
ASSERT_EQ(perf_context.db_mutex_lock_nanos, 0);
|
||||
get_perf_context()->Reset();
|
||||
ASSERT_EQ(get_perf_context()->db_mutex_lock_nanos, 0);
|
||||
mutex.Lock();
|
||||
mutex.Unlock();
|
||||
if (perf_level == PerfLevel::kEnableTimeExceptForMutex ||
|
||||
stats_code[c] != DB_MUTEX_WAIT_MICROS) {
|
||||
ASSERT_EQ(perf_context.db_mutex_lock_nanos, 0);
|
||||
ASSERT_EQ(get_perf_context()->db_mutex_lock_nanos, 0);
|
||||
} else {
|
||||
// increment the counter only when it's a DB Mutex
|
||||
ASSERT_GT(perf_context.db_mutex_lock_nanos, 0);
|
||||
ASSERT_GT(get_perf_context()->db_mutex_lock_nanos, 0);
|
||||
}
|
||||
});
|
||||
Env::Default()->SleepForMicroseconds(100);
|
||||
@ -591,28 +591,28 @@ TEST_F(PerfContextTest, FalseDBMutexWait) {
|
||||
for (int c = 0; c < 2; ++c) {
|
||||
InstrumentedMutex mutex(nullptr, Env::Default(), stats_code[c]);
|
||||
InstrumentedCondVar lock(&mutex);
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
mutex.Lock();
|
||||
lock.TimedWait(100);
|
||||
mutex.Unlock();
|
||||
if (stats_code[c] == static_cast<int>(DB_MUTEX_WAIT_MICROS)) {
|
||||
// increment the counter only when it's a DB Mutex
|
||||
ASSERT_GT(perf_context.db_condition_wait_nanos, 0);
|
||||
ASSERT_GT(get_perf_context()->db_condition_wait_nanos, 0);
|
||||
} else {
|
||||
ASSERT_EQ(perf_context.db_condition_wait_nanos, 0);
|
||||
ASSERT_EQ(get_perf_context()->db_condition_wait_nanos, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(PerfContextTest, ToString) {
|
||||
perf_context.Reset();
|
||||
perf_context.block_read_count = 12345;
|
||||
get_perf_context()->Reset();
|
||||
get_perf_context()->block_read_count = 12345;
|
||||
|
||||
std::string zero_included = perf_context.ToString();
|
||||
std::string zero_included = get_perf_context()->ToString();
|
||||
ASSERT_NE(std::string::npos, zero_included.find("= 0"));
|
||||
ASSERT_NE(std::string::npos, zero_included.find("= 12345"));
|
||||
|
||||
std::string zero_excluded = perf_context.ToString(true);
|
||||
std::string zero_excluded = get_perf_context()->ToString(true);
|
||||
ASSERT_EQ(std::string::npos, zero_excluded.find("= 0"));
|
||||
ASSERT_NE(std::string::npos, zero_excluded.find("= 12345"));
|
||||
}
|
||||
@ -633,36 +633,36 @@ TEST_F(PerfContextTest, MergeOperatorTime) {
|
||||
ASSERT_OK(db->Merge(WriteOptions(), "k1", "val4"));
|
||||
|
||||
SetPerfLevel(kEnableTime);
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
ASSERT_OK(db->Get(ReadOptions(), "k1", &val));
|
||||
#ifdef OS_SOLARIS
|
||||
for (int i = 0; i < 100; i++) {
|
||||
ASSERT_OK(db->Get(ReadOptions(), "k1", &val));
|
||||
}
|
||||
#endif
|
||||
EXPECT_GT(perf_context.merge_operator_time_nanos, 0);
|
||||
EXPECT_GT(get_perf_context()->merge_operator_time_nanos, 0);
|
||||
|
||||
ASSERT_OK(db->Flush(FlushOptions()));
|
||||
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
ASSERT_OK(db->Get(ReadOptions(), "k1", &val));
|
||||
#ifdef OS_SOLARIS
|
||||
for (int i = 0; i < 100; i++) {
|
||||
ASSERT_OK(db->Get(ReadOptions(), "k1", &val));
|
||||
}
|
||||
#endif
|
||||
EXPECT_GT(perf_context.merge_operator_time_nanos, 0);
|
||||
EXPECT_GT(get_perf_context()->merge_operator_time_nanos, 0);
|
||||
|
||||
ASSERT_OK(db->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
ASSERT_OK(db->Get(ReadOptions(), "k1", &val));
|
||||
#ifdef OS_SOLARIS
|
||||
for (int i = 0; i < 100; i++) {
|
||||
ASSERT_OK(db->Get(ReadOptions(), "k1", &val));
|
||||
}
|
||||
#endif
|
||||
EXPECT_GT(perf_context.merge_operator_time_nanos, 0);
|
||||
EXPECT_GT(get_perf_context()->merge_operator_time_nanos, 0);
|
||||
|
||||
delete db;
|
||||
}
|
||||
|
@ -605,11 +605,11 @@ TEST_F(PrefixTest, DynamicPrefixIterator) {
|
||||
Slice key = TestKeyToSlice(s, test_key);
|
||||
std::string value(FLAGS_value_size, 0);
|
||||
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
StopWatchNano timer(Env::Default(), true);
|
||||
ASSERT_OK(db->Put(write_options, key, value));
|
||||
hist_put_time.Add(timer.ElapsedNanos());
|
||||
hist_put_comparison.Add(perf_context.user_key_comparison_count);
|
||||
hist_put_comparison.Add(get_perf_context()->user_key_comparison_count);
|
||||
}
|
||||
}
|
||||
|
||||
@ -628,7 +628,7 @@ TEST_F(PrefixTest, DynamicPrefixIterator) {
|
||||
Slice key = TestKeyToSlice(s, test_key);
|
||||
std::string value = "v" + ToString(0);
|
||||
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
StopWatchNano timer(Env::Default(), true);
|
||||
auto key_prefix = options.prefix_extractor->Transform(key);
|
||||
uint64_t total_keys = 0;
|
||||
@ -642,7 +642,7 @@ TEST_F(PrefixTest, DynamicPrefixIterator) {
|
||||
total_keys++;
|
||||
}
|
||||
hist_seek_time.Add(timer.ElapsedNanos());
|
||||
hist_seek_comparison.Add(perf_context.user_key_comparison_count);
|
||||
hist_seek_comparison.Add(get_perf_context()->user_key_comparison_count);
|
||||
ASSERT_EQ(total_keys, FLAGS_items_per_prefix - FLAGS_items_per_prefix/2);
|
||||
}
|
||||
|
||||
@ -662,11 +662,11 @@ TEST_F(PrefixTest, DynamicPrefixIterator) {
|
||||
std::string s;
|
||||
Slice key = TestKeyToSlice(s, test_key);
|
||||
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
StopWatchNano timer(Env::Default(), true);
|
||||
iter->Seek(key);
|
||||
hist_no_seek_time.Add(timer.ElapsedNanos());
|
||||
hist_no_seek_comparison.Add(perf_context.user_key_comparison_count);
|
||||
hist_no_seek_comparison.Add(get_perf_context()->user_key_comparison_count);
|
||||
ASSERT_TRUE(!iter->Valid());
|
||||
}
|
||||
|
||||
|
@ -46,13 +46,7 @@ struct IOStatsContext {
|
||||
uint64_t logger_nanos;
|
||||
};
|
||||
|
||||
#ifdef ROCKSDB_SUPPORT_THREAD_LOCAL
|
||||
#if defined(_MSC_VER) && !defined(__thread)
|
||||
// Thread local storage on Linux
|
||||
// There is thread_local in C++11
|
||||
#define __thread __declspec(thread)
|
||||
#endif
|
||||
extern __thread IOStatsContext iostats_context;
|
||||
#endif
|
||||
// Get Thread-local IOStatsContext object pointer
|
||||
IOStatsContext* get_iostats_context();
|
||||
|
||||
} // namespace rocksdb
|
||||
|
@ -150,21 +150,10 @@ struct PerfContext {
|
||||
uint64_t env_new_logger_nanos;
|
||||
};
|
||||
|
||||
#if defined(NPERF_CONTEXT) || !defined(ROCKSDB_SUPPORT_THREAD_LOCAL)
|
||||
extern PerfContext perf_context;
|
||||
#else
|
||||
#if defined(OS_SOLARIS)
|
||||
PerfContext *getPerfContext();
|
||||
#define perf_context (*getPerfContext())
|
||||
#else
|
||||
#if defined(_MSC_VER) && !defined(__thread)
|
||||
// Thread local storage on Linux
|
||||
// There is thread_local in C++11
|
||||
#define __thread __declspec(thread)
|
||||
#endif
|
||||
extern __thread PerfContext perf_context;
|
||||
#endif
|
||||
#endif
|
||||
// Get Thread-local PerfContext object pointer
|
||||
// if defined(NPERF_CONTEXT), then the pointer is not thread-local
|
||||
PerfContext* get_perf_context();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,6 @@
|
||||
namespace rocksdb {
|
||||
|
||||
// How much perf stats to collect. Affects perf_context and iostats_context.
|
||||
|
||||
enum PerfLevel : unsigned char {
|
||||
kUninitialized = 0, // unknown setting
|
||||
kDisable = 1, // disable perf stats
|
||||
|
@ -6,12 +6,21 @@
|
||||
#include <sstream>
|
||||
#include "monitoring/iostats_context_imp.h"
|
||||
#include "rocksdb/env.h"
|
||||
#include "util/thread_local.h"
|
||||
|
||||
namespace rocksdb {
|
||||
|
||||
#ifdef ROCKSDB_SUPPORT_THREAD_LOCAL
|
||||
__thread IOStatsContext iostats_context;
|
||||
#endif
|
||||
ThreadLocalPtr iostats_context([](void* ptr) {
|
||||
auto* p = static_cast<IOStatsContext*>(ptr);
|
||||
delete p;
|
||||
});
|
||||
|
||||
IOStatsContext* get_iostats_context() {
|
||||
if (iostats_context.Get() == nullptr) {
|
||||
iostats_context.Reset(static_cast<void*>(new IOStatsContext()));
|
||||
}
|
||||
return static_cast<IOStatsContext*>(iostats_context.Get());
|
||||
}
|
||||
|
||||
void IOStatsContext::Reset() {
|
||||
thread_pool_id = Env::Priority::TOTAL;
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
// increment a specific counter by the specified value
|
||||
#define IOSTATS_ADD(metric, value) \
|
||||
(iostats_context.metric += value)
|
||||
(get_iostats_context()->metric += value)
|
||||
|
||||
// Increase metric value only when it is positive
|
||||
#define IOSTATS_ADD_IF_POSITIVE(metric, value) \
|
||||
@ -21,25 +21,25 @@
|
||||
|
||||
// reset a specific counter to zero
|
||||
#define IOSTATS_RESET(metric) \
|
||||
(iostats_context.metric = 0)
|
||||
(get_iostats_context()->metric = 0)
|
||||
|
||||
// reset all counters to zero
|
||||
#define IOSTATS_RESET_ALL() \
|
||||
(iostats_context.Reset())
|
||||
(get_iostats_context()->Reset())
|
||||
|
||||
#define IOSTATS_SET_THREAD_POOL_ID(value) \
|
||||
(iostats_context.thread_pool_id = value)
|
||||
(get_iostats_context()->thread_pool_id = value)
|
||||
|
||||
#define IOSTATS_THREAD_POOL_ID() \
|
||||
(iostats_context.thread_pool_id)
|
||||
(get_iostats_context()->thread_pool_id)
|
||||
|
||||
#define IOSTATS(metric) \
|
||||
(iostats_context.metric)
|
||||
(get_iostats_context()->metric)
|
||||
|
||||
// Declare and set start time of the timer
|
||||
#define IOSTATS_TIMER_GUARD(metric) \
|
||||
PerfStepTimer iostats_step_timer_ ## metric(&(iostats_context.metric)); \
|
||||
iostats_step_timer_ ## metric.Start();
|
||||
#define IOSTATS_TIMER_GUARD(metric) \
|
||||
PerfStepTimer iostats_step_timer_##metric(&(get_iostats_context()->metric)); \
|
||||
iostats_step_timer_##metric.Start();
|
||||
|
||||
#else // ROCKSDB_SUPPORT_THREAD_LOCAL
|
||||
|
||||
|
@ -9,14 +9,14 @@
|
||||
namespace rocksdb {
|
||||
|
||||
TEST(IOStatsContextTest, ToString) {
|
||||
iostats_context.Reset();
|
||||
iostats_context.bytes_read = 12345;
|
||||
get_iostats_context()->Reset();
|
||||
get_iostats_context()->bytes_read = 12345;
|
||||
|
||||
std::string zero_included = iostats_context.ToString();
|
||||
std::string zero_included = get_iostats_context()->ToString();
|
||||
ASSERT_NE(std::string::npos, zero_included.find("= 0"));
|
||||
ASSERT_NE(std::string::npos, zero_included.find("= 12345"));
|
||||
|
||||
std::string zero_excluded = iostats_context.ToString(true);
|
||||
std::string zero_excluded = get_iostats_context()->ToString(true);
|
||||
ASSERT_EQ(std::string::npos, zero_excluded.find("= 0"));
|
||||
ASSERT_NE(std::string::npos, zero_excluded.find("= 12345"));
|
||||
}
|
||||
|
@ -8,21 +8,32 @@
|
||||
|
||||
#include <sstream>
|
||||
#include "monitoring/perf_context_imp.h"
|
||||
#include "util/thread_local.h"
|
||||
|
||||
namespace rocksdb {
|
||||
|
||||
#if defined(NPERF_CONTEXT) || !defined(ROCKSDB_SUPPORT_THREAD_LOCAL)
|
||||
PerfContext perf_context;
|
||||
#ifdef NPERF_CONTEXT
|
||||
PerfContext perf_context;
|
||||
#else
|
||||
#if defined(OS_SOLARIS)
|
||||
__thread PerfContext perf_context_;
|
||||
#else
|
||||
__thread PerfContext perf_context;
|
||||
#endif
|
||||
ThreadLocalPtr perf_context([](void* ptr) {
|
||||
auto* p = static_cast<PerfContext*>(ptr);
|
||||
delete p;
|
||||
});
|
||||
#endif
|
||||
|
||||
PerfContext* get_perf_context() {
|
||||
#ifdef NPERF_CONTEXT
|
||||
return &perf_context;
|
||||
#else
|
||||
if (perf_context.Get() == nullptr) {
|
||||
perf_context.Reset(static_cast<void*>(new PerfContext()));
|
||||
}
|
||||
return static_cast<PerfContext*>(perf_context.Get());
|
||||
#endif
|
||||
}
|
||||
|
||||
void PerfContext::Reset() {
|
||||
#if !defined(NPERF_CONTEXT) && defined(ROCKSDB_SUPPORT_THREAD_LOCAL)
|
||||
#ifndef NPERF_CONTEXT
|
||||
user_key_comparison_count = 0;
|
||||
block_cache_hit_count = 0;
|
||||
block_read_count = 0;
|
||||
@ -96,7 +107,7 @@ void PerfContext::Reset() {
|
||||
}
|
||||
|
||||
std::string PerfContext::ToString(bool exclude_zero_counters) const {
|
||||
#if defined(NPERF_CONTEXT) || !defined(ROCKSDB_SUPPORT_THREAD_LOCAL)
|
||||
#ifdef NPERF_CONTEXT
|
||||
return "";
|
||||
#else
|
||||
std::ostringstream ss;
|
||||
@ -166,10 +177,4 @@ std::string PerfContext::ToString(bool exclude_zero_counters) const {
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(OS_SOLARIS)
|
||||
PerfContext *getPerfContext() {
|
||||
return &perf_context_;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
namespace rocksdb {
|
||||
|
||||
#if defined(NPERF_CONTEXT) || !defined(ROCKSDB_SUPPORT_THREAD_LOCAL)
|
||||
#if defined(NPERF_CONTEXT)
|
||||
|
||||
#define PERF_TIMER_GUARD(metric)
|
||||
#define PERF_CONDITIONAL_TIMER_FOR_MUTEX_GUARD(metric, condition)
|
||||
@ -24,31 +24,27 @@ namespace rocksdb {
|
||||
#else
|
||||
|
||||
// Stop the timer and update the metric
|
||||
#define PERF_TIMER_STOP(metric) \
|
||||
perf_step_timer_ ## metric.Stop();
|
||||
#define PERF_TIMER_STOP(metric) perf_step_timer_##metric.Stop();
|
||||
|
||||
#define PERF_TIMER_START(metric) \
|
||||
perf_step_timer_ ## metric.Start();
|
||||
#define PERF_TIMER_START(metric) perf_step_timer_##metric.Start();
|
||||
|
||||
// Declare and set start time of the timer
|
||||
#define PERF_TIMER_GUARD(metric) \
|
||||
PerfStepTimer perf_step_timer_ ## metric(&(perf_context.metric)); \
|
||||
perf_step_timer_ ## metric.Start();
|
||||
#define PERF_TIMER_GUARD(metric) \
|
||||
PerfStepTimer perf_step_timer_##metric(&(get_perf_context()->metric)); \
|
||||
perf_step_timer_##metric.Start();
|
||||
|
||||
#define PERF_CONDITIONAL_TIMER_FOR_MUTEX_GUARD(metric, condition) \
|
||||
PerfStepTimer perf_step_timer_##metric(&(perf_context.metric), true); \
|
||||
if ((condition)) { \
|
||||
perf_step_timer_##metric.Start(); \
|
||||
#define PERF_CONDITIONAL_TIMER_FOR_MUTEX_GUARD(metric, condition) \
|
||||
PerfStepTimer perf_step_timer_##metric(&(get_perf_context()->metric), true); \
|
||||
if ((condition)) { \
|
||||
perf_step_timer_##metric.Start(); \
|
||||
}
|
||||
|
||||
// Update metric with time elapsed since last START. start time is reset
|
||||
// to current timestamp.
|
||||
#define PERF_TIMER_MEASURE(metric) \
|
||||
perf_step_timer_ ## metric.Measure();
|
||||
#define PERF_TIMER_MEASURE(metric) perf_step_timer_##metric.Measure();
|
||||
|
||||
// Increase metric value
|
||||
#define PERF_COUNTER_ADD(metric, value) \
|
||||
perf_context.metric += value;
|
||||
#define PERF_COUNTER_ADD(metric, value) get_perf_context()->metric += value;
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -2085,14 +2085,14 @@ TEST_F(BlockBasedTableTest, BlockReadCountTest) {
|
||||
GetContext get_context(options.comparator, nullptr, nullptr, nullptr,
|
||||
GetContext::kNotFound, user_key, &value, nullptr,
|
||||
nullptr, nullptr, nullptr);
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
ASSERT_OK(reader->Get(ReadOptions(), encoded_key, &get_context));
|
||||
if (index_and_filter_in_cache) {
|
||||
// data, index and filter block
|
||||
ASSERT_EQ(perf_context.block_read_count, 3);
|
||||
ASSERT_EQ(get_perf_context()->block_read_count, 3);
|
||||
} else {
|
||||
// just the data block
|
||||
ASSERT_EQ(perf_context.block_read_count, 1);
|
||||
ASSERT_EQ(get_perf_context()->block_read_count, 1);
|
||||
}
|
||||
ASSERT_EQ(get_context.State(), GetContext::kFound);
|
||||
ASSERT_STREQ(value.data(), "hello");
|
||||
@ -2106,22 +2106,22 @@ TEST_F(BlockBasedTableTest, BlockReadCountTest) {
|
||||
get_context = GetContext(options.comparator, nullptr, nullptr, nullptr,
|
||||
GetContext::kNotFound, user_key, &value, nullptr,
|
||||
nullptr, nullptr, nullptr);
|
||||
perf_context.Reset();
|
||||
get_perf_context()->Reset();
|
||||
ASSERT_OK(reader->Get(ReadOptions(), encoded_key, &get_context));
|
||||
ASSERT_EQ(get_context.State(), GetContext::kNotFound);
|
||||
|
||||
if (index_and_filter_in_cache) {
|
||||
if (bloom_filter_type == 0) {
|
||||
// with block-based, we read index and then the filter
|
||||
ASSERT_EQ(perf_context.block_read_count, 2);
|
||||
ASSERT_EQ(get_perf_context()->block_read_count, 2);
|
||||
} else {
|
||||
// with full-filter, we read filter first and then we stop
|
||||
ASSERT_EQ(perf_context.block_read_count, 1);
|
||||
ASSERT_EQ(get_perf_context()->block_read_count, 1);
|
||||
}
|
||||
} else {
|
||||
// filter is already in memory and it figures out that the key doesn't
|
||||
// exist
|
||||
ASSERT_EQ(perf_context.block_read_count, 0);
|
||||
ASSERT_EQ(get_perf_context()->block_read_count, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3840,7 +3840,7 @@ void VerifyDBFromDB(std::string& truth_db_name) {
|
||||
delete iter;
|
||||
thread->stats.AddBytes(bytes);
|
||||
if (FLAGS_perf_level > rocksdb::PerfLevel::kDisable) {
|
||||
thread->stats.AddMessage(perf_context.ToString());
|
||||
thread->stats.AddMessage(get_perf_context()->ToString());
|
||||
}
|
||||
}
|
||||
|
||||
@ -3921,7 +3921,7 @@ void VerifyDBFromDB(std::string& truth_db_name) {
|
||||
thread->stats.AddMessage(msg);
|
||||
|
||||
if (FLAGS_perf_level > rocksdb::PerfLevel::kDisable) {
|
||||
thread->stats.AddMessage(perf_context.ToString());
|
||||
thread->stats.AddMessage(get_perf_context()->ToString());
|
||||
}
|
||||
}
|
||||
|
||||
@ -4006,7 +4006,7 @@ void VerifyDBFromDB(std::string& truth_db_name) {
|
||||
thread->stats.AddMessage(msg);
|
||||
|
||||
if (FLAGS_perf_level > rocksdb::PerfLevel::kDisable) {
|
||||
thread->stats.AddMessage(perf_context.ToString());
|
||||
thread->stats.AddMessage(get_perf_context()->ToString());
|
||||
}
|
||||
}
|
||||
|
||||
@ -4162,7 +4162,7 @@ void VerifyDBFromDB(std::string& truth_db_name) {
|
||||
thread->stats.AddBytes(bytes);
|
||||
thread->stats.AddMessage(msg);
|
||||
if (FLAGS_perf_level > rocksdb::PerfLevel::kDisable) {
|
||||
thread->stats.AddMessage(perf_context.ToString());
|
||||
thread->stats.AddMessage(get_perf_context()->ToString());
|
||||
}
|
||||
}
|
||||
|
||||
@ -4816,7 +4816,7 @@ void VerifyDBFromDB(std::string& truth_db_name) {
|
||||
thread->stats.AddMessage(msg);
|
||||
|
||||
if (FLAGS_perf_level > rocksdb::PerfLevel::kDisable) {
|
||||
thread->stats.AddMessage(perf_context.ToString());
|
||||
thread->stats.AddMessage(get_perf_context()->ToString());
|
||||
}
|
||||
}
|
||||
|
||||
@ -4977,7 +4977,7 @@ void VerifyDBFromDB(std::string& truth_db_name) {
|
||||
thread->stats.AddBytes(bytes);
|
||||
thread->stats.AddMessage(msg);
|
||||
if (FLAGS_perf_level > rocksdb::PerfLevel::kDisable) {
|
||||
thread->stats.AddMessage(perf_context.ToString());
|
||||
thread->stats.AddMessage(get_perf_context()->ToString());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,53 +67,54 @@ TEST_F(ThreadLocalTest, UniqueIdTest) {
|
||||
port::Mutex mu;
|
||||
port::CondVar cv(&mu);
|
||||
|
||||
ASSERT_EQ(IDChecker::PeekId(), 0u);
|
||||
// perf_context and iostats_context take 2 ids
|
||||
ASSERT_EQ(IDChecker::PeekId(), 2u);
|
||||
// New ThreadLocal instance bumps id by 1
|
||||
{
|
||||
// Id used 0
|
||||
Params p1(&mu, &cv, nullptr, 1u);
|
||||
ASSERT_EQ(IDChecker::PeekId(), 1u);
|
||||
// Id used 1
|
||||
Params p2(&mu, &cv, nullptr, 1u);
|
||||
ASSERT_EQ(IDChecker::PeekId(), 2u);
|
||||
// Id used 2
|
||||
Params p3(&mu, &cv, nullptr, 1u);
|
||||
Params p1(&mu, &cv, nullptr, 1u);
|
||||
ASSERT_EQ(IDChecker::PeekId(), 3u);
|
||||
// Id used 3
|
||||
Params p4(&mu, &cv, nullptr, 1u);
|
||||
Params p2(&mu, &cv, nullptr, 1u);
|
||||
ASSERT_EQ(IDChecker::PeekId(), 4u);
|
||||
// Id used 4
|
||||
Params p3(&mu, &cv, nullptr, 1u);
|
||||
ASSERT_EQ(IDChecker::PeekId(), 5u);
|
||||
// Id used 5
|
||||
Params p4(&mu, &cv, nullptr, 1u);
|
||||
ASSERT_EQ(IDChecker::PeekId(), 6u);
|
||||
}
|
||||
// id 3, 2, 1, 0 are in the free queue in order
|
||||
ASSERT_EQ(IDChecker::PeekId(), 0u);
|
||||
|
||||
// pick up 0
|
||||
Params p1(&mu, &cv, nullptr, 1u);
|
||||
ASSERT_EQ(IDChecker::PeekId(), 1u);
|
||||
// pick up 1
|
||||
Params* p2 = new Params(&mu, &cv, nullptr, 1u);
|
||||
// id 5, 4, 3, 2 are in the free queue in order
|
||||
ASSERT_EQ(IDChecker::PeekId(), 2u);
|
||||
|
||||
// pick up 2
|
||||
Params p3(&mu, &cv, nullptr, 1u);
|
||||
ASSERT_EQ(IDChecker::PeekId(), 3u);
|
||||
// return up 1
|
||||
delete p2;
|
||||
ASSERT_EQ(IDChecker::PeekId(), 1u);
|
||||
// Now we have 3, 1 in queue
|
||||
// pick up 1
|
||||
Params p4(&mu, &cv, nullptr, 1u);
|
||||
Params p1(&mu, &cv, nullptr, 1u);
|
||||
ASSERT_EQ(IDChecker::PeekId(), 3u);
|
||||
// pick up 3
|
||||
Params* p2 = new Params(&mu, &cv, nullptr, 1u);
|
||||
ASSERT_EQ(IDChecker::PeekId(), 4u);
|
||||
// pick up 4
|
||||
Params p3(&mu, &cv, nullptr, 1u);
|
||||
ASSERT_EQ(IDChecker::PeekId(), 5u);
|
||||
// return up 3
|
||||
delete p2;
|
||||
ASSERT_EQ(IDChecker::PeekId(), 3u);
|
||||
// Now we have 4, 2 in queue
|
||||
// pick up 3
|
||||
Params p4(&mu, &cv, nullptr, 1u);
|
||||
ASSERT_EQ(IDChecker::PeekId(), 5u);
|
||||
// pick up 5
|
||||
Params p5(&mu, &cv, nullptr, 1u);
|
||||
// next new id
|
||||
ASSERT_EQ(IDChecker::PeekId(), 4u);
|
||||
ASSERT_EQ(IDChecker::PeekId(), 6u);
|
||||
// After exit, id sequence in queue:
|
||||
// 3, 1, 2, 0
|
||||
// 5, 4, 3, 2(, 1, 0)
|
||||
}
|
||||
#endif // __clang_analyzer__
|
||||
|
||||
TEST_F(ThreadLocalTest, SequentialReadWriteTest) {
|
||||
// global id list carries over 3, 1, 2, 0
|
||||
ASSERT_EQ(IDChecker::PeekId(), 0u);
|
||||
// global id list carries over 5, 4, 3, 2
|
||||
ASSERT_EQ(IDChecker::PeekId(), 2u);
|
||||
|
||||
port::Mutex mu;
|
||||
port::CondVar cv(&mu);
|
||||
@ -143,7 +144,7 @@ TEST_F(ThreadLocalTest, SequentialReadWriteTest) {
|
||||
};
|
||||
|
||||
for (int iter = 0; iter < 1024; ++iter) {
|
||||
ASSERT_EQ(IDChecker::PeekId(), 1u);
|
||||
ASSERT_EQ(IDChecker::PeekId(), 3u);
|
||||
// Another new thread, read/write should not see value from previous thread
|
||||
env_->StartThread(func, static_cast<void*>(&p));
|
||||
mu.Lock();
|
||||
@ -151,13 +152,13 @@ TEST_F(ThreadLocalTest, SequentialReadWriteTest) {
|
||||
cv.Wait();
|
||||
}
|
||||
mu.Unlock();
|
||||
ASSERT_EQ(IDChecker::PeekId(), 1u);
|
||||
ASSERT_EQ(IDChecker::PeekId(), 3u);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ThreadLocalTest, ConcurrentReadWriteTest) {
|
||||
// global id list carries over 3, 1, 2, 0
|
||||
ASSERT_EQ(IDChecker::PeekId(), 0u);
|
||||
// global id list carries over 5, 4, 3, 2
|
||||
ASSERT_EQ(IDChecker::PeekId(), 2u);
|
||||
|
||||
ThreadLocalPtr tls2;
|
||||
port::Mutex mu1;
|
||||
@ -238,11 +239,11 @@ TEST_F(ThreadLocalTest, ConcurrentReadWriteTest) {
|
||||
}
|
||||
mu2.Unlock();
|
||||
|
||||
ASSERT_EQ(IDChecker::PeekId(), 3u);
|
||||
ASSERT_EQ(IDChecker::PeekId(), 5u);
|
||||
}
|
||||
|
||||
TEST_F(ThreadLocalTest, Unref) {
|
||||
ASSERT_EQ(IDChecker::PeekId(), 0u);
|
||||
ASSERT_EQ(IDChecker::PeekId(), 2u);
|
||||
|
||||
auto unref = [](void* ptr) {
|
||||
auto& p = *static_cast<Params*>(ptr);
|
||||
|
@ -16,14 +16,14 @@ class TimedEnvTest : public testing::Test {
|
||||
|
||||
TEST_F(TimedEnvTest, BasicTest) {
|
||||
SetPerfLevel(PerfLevel::kEnableTime);
|
||||
ASSERT_EQ(0, perf_context.env_new_writable_file_nanos);
|
||||
ASSERT_EQ(0, get_perf_context()->env_new_writable_file_nanos);
|
||||
|
||||
std::unique_ptr<Env> mem_env(NewMemEnv(Env::Default()));
|
||||
std::unique_ptr<Env> timed_env(NewTimedEnv(mem_env.get()));
|
||||
std::unique_ptr<WritableFile> writable_file;
|
||||
timed_env->NewWritableFile("f", &writable_file, EnvOptions());
|
||||
|
||||
ASSERT_GT(perf_context.env_new_writable_file_nanos, 0);
|
||||
ASSERT_GT(get_perf_context()->env_new_writable_file_nanos, 0);
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
|
Loading…
Reference in New Issue
Block a user