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
main
Aaron Gao 8 years ago committed by Facebook Github Bot
parent 138b87eae4
commit 7f6c02dda1
  1. 1
      HISTORY.md
  2. 8
      db/db_basic_test.cc
  3. 48
      db/db_bloom_filter_test.cc
  4. 8
      db/db_iter_test.cc
  5. 28
      db/db_iterator_test.cc
  6. 38
      db/db_properties_test.cc
  7. 146
      db/perf_context_test.cc
  8. 12
      db/prefix_test.cc
  9. 10
      include/rocksdb/iostats_context.h
  10. 19
      include/rocksdb/perf_context.h
  11. 1
      include/rocksdb/perf_level.h
  12. 15
      monitoring/iostats_context.cc
  13. 16
      monitoring/iostats_context_imp.h
  14. 8
      monitoring/iostats_context_test.cc
  15. 35
      monitoring/perf_context.cc
  16. 20
      monitoring/perf_context_imp.h
  17. 14
      table/table_test.cc
  18. 12
      tools/db_bench_tool.cc
  19. 65
      util/thread_local_test.cc
  20. 4
      utilities/env_timed_test.cc

@ -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);
perf_context.Reset();
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);
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);
perf_context.Reset();
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);
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();
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();
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); \
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);
// id 5, 4, 3, 2 are in the free queue in order
ASSERT_EQ(IDChecker::PeekId(), 2u);
// pick up 0
// pick up 2
Params p1(&mu, &cv, nullptr, 1u);
ASSERT_EQ(IDChecker::PeekId(), 1u);
// pick up 1
ASSERT_EQ(IDChecker::PeekId(), 3u);
// pick up 3
Params* p2 = new Params(&mu, &cv, nullptr, 1u);
ASSERT_EQ(IDChecker::PeekId(), 2u);
// pick up 2
ASSERT_EQ(IDChecker::PeekId(), 4u);
// pick up 4
Params p3(&mu, &cv, nullptr, 1u);
ASSERT_EQ(IDChecker::PeekId(), 3u);
// return up 1
ASSERT_EQ(IDChecker::PeekId(), 5u);
// return up 3
delete p2;
ASSERT_EQ(IDChecker::PeekId(), 1u);
// Now we have 3, 1 in queue
// pick up 1
Params p4(&mu, &cv, nullptr, 1u);
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…
Cancel
Save