revert perf_context and io_stats to __thread

Summary:
https://github.com/facebook/rocksdb/pull/2380 introduces a regression by replacing __thread with ThreadLocalPtr. Revert the thread local implementation back.
Closes https://github.com/facebook/rocksdb/pull/2485

Differential Revision: D5308050

Pulled By: lightmark

fbshipit-source-id: 2676e9c22edf76e8133d3f4c50e2711e11a95480
This commit is contained in:
Aaron Gao 2017-06-26 15:13:35 -07:00 committed by Facebook Github Bot
parent 5c97a7c066
commit 0025a36409
5 changed files with 57 additions and 55 deletions

View File

@ -154,7 +154,6 @@ struct PerfContext {
// if defined(NPERF_CONTEXT), then the pointer is not thread-local
PerfContext* get_perf_context();
}
#endif

View File

@ -10,16 +10,16 @@
namespace rocksdb {
ThreadLocalPtr iostats_context([](void* ptr) {
auto* p = static_cast<IOStatsContext*>(ptr);
delete p;
});
#ifdef ROCKSDB_SUPPORT_THREAD_LOCAL
__thread IOStatsContext iostats_context;
#endif
IOStatsContext* get_iostats_context() {
if (iostats_context.Get() == nullptr) {
iostats_context.Reset(static_cast<void*>(new IOStatsContext()));
}
return static_cast<IOStatsContext*>(iostats_context.Get());
#ifdef ROCKSDB_SUPPORT_THREAD_LOCAL
return &iostats_context;
#else
return nullptr;
#endif
}
void IOStatsContext::Reset() {

View File

@ -8,27 +8,28 @@
#include <sstream>
#include "monitoring/perf_context_imp.h"
#include "util/thread_local.h"
namespace rocksdb {
#ifdef NPERF_CONTEXT
#if defined(NPERF_CONTEXT) || !defined(ROCKSDB_SUPPORT_THREAD_LOCAL)
PerfContext perf_context;
#else
ThreadLocalPtr perf_context([](void* ptr) {
auto* p = static_cast<PerfContext*>(ptr);
delete p;
});
#if defined(OS_SOLARIS)
__thread PerfContext perf_context_;
#else
__thread PerfContext perf_context;
#endif
#endif
PerfContext* get_perf_context() {
#ifdef NPERF_CONTEXT
#if defined(NPERF_CONTEXT) || !defined(ROCKSDB_SUPPORT_THREAD_LOCAL)
return &perf_context;
#else
if (perf_context.Get() == nullptr) {
perf_context.Reset(static_cast<void*>(new PerfContext()));
}
return static_cast<PerfContext*>(perf_context.Get());
#if defined(OS_SOLARIS)
return &perf_context_;
#else
return &perf_context;
#endif
#endif
}

View File

@ -44,7 +44,10 @@ namespace rocksdb {
#define PERF_TIMER_MEASURE(metric) perf_step_timer_##metric.Measure();
// Increase metric value
#define PERF_COUNTER_ADD(metric, value) get_perf_context()->metric += value;
#define PERF_COUNTER_ADD(metric, value) \
if (perf_level >= PerfLevel::kEnableCount) { \
get_perf_context()->metric += value; \
}
#endif

View File

@ -67,54 +67,53 @@ TEST_F(ThreadLocalTest, UniqueIdTest) {
port::Mutex mu;
port::CondVar cv(&mu);
// perf_context and iostats_context take 2 ids
ASSERT_EQ(IDChecker::PeekId(), 2u);
ASSERT_EQ(IDChecker::PeekId(), 0u);
// New ThreadLocal instance bumps id by 1
{
// Id used 2
// 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);
ASSERT_EQ(IDChecker::PeekId(), 3u);
// Id used 3
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);
ASSERT_EQ(IDChecker::PeekId(), 4u);
}
// id 5, 4, 3, 2 are in the free queue in order
ASSERT_EQ(IDChecker::PeekId(), 2u);
// id 3, 2, 1, 0 are in the free queue in order
ASSERT_EQ(IDChecker::PeekId(), 0u);
// pick up 2
// pick up 0
Params p1(&mu, &cv, nullptr, 1u);
ASSERT_EQ(IDChecker::PeekId(), 3u);
// pick up 3
ASSERT_EQ(IDChecker::PeekId(), 1u);
// pick up 1
Params* p2 = new Params(&mu, &cv, nullptr, 1u);
ASSERT_EQ(IDChecker::PeekId(), 4u);
// pick up 4
ASSERT_EQ(IDChecker::PeekId(), 2u);
// pick up 2
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
// 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);
ASSERT_EQ(IDChecker::PeekId(), 5u);
// pick up 5
ASSERT_EQ(IDChecker::PeekId(), 3u);
// pick up 3
Params p5(&mu, &cv, nullptr, 1u);
// next new id
ASSERT_EQ(IDChecker::PeekId(), 6u);
ASSERT_EQ(IDChecker::PeekId(), 4u);
// After exit, id sequence in queue:
// 5, 4, 3, 2(, 1, 0)
// 3, 1, 2, 0
}
#endif // __clang_analyzer__
TEST_F(ThreadLocalTest, SequentialReadWriteTest) {
// global id list carries over 5, 4, 3, 2
ASSERT_EQ(IDChecker::PeekId(), 2u);
// global id list carries over 3, 1, 2, 0
ASSERT_EQ(IDChecker::PeekId(), 0u);
port::Mutex mu;
port::CondVar cv(&mu);
@ -144,7 +143,7 @@ TEST_F(ThreadLocalTest, SequentialReadWriteTest) {
};
for (int iter = 0; iter < 1024; ++iter) {
ASSERT_EQ(IDChecker::PeekId(), 3u);
ASSERT_EQ(IDChecker::PeekId(), 1u);
// Another new thread, read/write should not see value from previous thread
env_->StartThread(func, static_cast<void*>(&p));
mu.Lock();
@ -152,13 +151,13 @@ TEST_F(ThreadLocalTest, SequentialReadWriteTest) {
cv.Wait();
}
mu.Unlock();
ASSERT_EQ(IDChecker::PeekId(), 3u);
ASSERT_EQ(IDChecker::PeekId(), 1u);
}
}
TEST_F(ThreadLocalTest, ConcurrentReadWriteTest) {
// global id list carries over 5, 4, 3, 2
ASSERT_EQ(IDChecker::PeekId(), 2u);
// global id list carries over 3, 1, 2, 0
ASSERT_EQ(IDChecker::PeekId(), 0u);
ThreadLocalPtr tls2;
port::Mutex mu1;
@ -239,11 +238,11 @@ TEST_F(ThreadLocalTest, ConcurrentReadWriteTest) {
}
mu2.Unlock();
ASSERT_EQ(IDChecker::PeekId(), 5u);
ASSERT_EQ(IDChecker::PeekId(), 3u);
}
TEST_F(ThreadLocalTest, Unref) {
ASSERT_EQ(IDChecker::PeekId(), 2u);
ASSERT_EQ(IDChecker::PeekId(), 0u);
auto unref = [](void* ptr) {
auto& p = *static_cast<Params*>(ptr);