Commit faa75f83 authored by Andrii Grynenko's avatar Andrii Grynenko Committed by facebook-github-bot-4

Improve folly::Singleton try_get perf and bring back raw get benchmark

Reviewed By: elsteveogrande

Differential Revision: D2517522

fb-gh-sync-id: eab11d17ce5db94e09aa733b6067e44d36be6345
parent a40474b5
......@@ -76,7 +76,8 @@ void SingletonHolder<T>::registerSingletonMock(CreateFunc c, TeardownFunc t) {
template <typename T>
T* SingletonHolder<T>::get() {
if (LIKELY(state_ == SingletonHolderState::Living)) {
if (LIKELY(state_.load(std::memory_order_acquire) ==
SingletonHolderState::Living)) {
return instance_ptr_;
}
createInstance();
......@@ -93,13 +94,24 @@ T* SingletonHolder<T>::get() {
template <typename T>
std::weak_ptr<T> SingletonHolder<T>::get_weak() {
if (UNLIKELY(state_ != SingletonHolderState::Living)) {
if (UNLIKELY(state_.load(std::memory_order_acquire) !=
SingletonHolderState::Living)) {
createInstance();
}
return instance_weak_;
}
template <typename T>
std::shared_ptr<T> SingletonHolder<T>::try_get() {
if (UNLIKELY(state_.load(std::memory_order_acquire) !=
SingletonHolderState::Living)) {
createInstance();
}
return instance_weak_.lock();
}
template <typename T>
TypeDescriptor SingletonHolder<T>::type() {
return type_;
......
......@@ -243,6 +243,7 @@ struct SingletonHolder : public SingletonHolderBase {
inline T* get();
inline std::weak_ptr<T> get_weak();
inline std::shared_ptr<T> try_get();
void registerSingleton(CreateFunc c, TeardownFunc t);
void registerSingletonMock(CreateFunc c, TeardownFunc t);
......@@ -494,7 +495,7 @@ class Singleton {
// Avoid holding these shared_ptrs beyond the scope of a function;
// don't put them in member variables, always use try_get() instead
static std::shared_ptr<T> try_get() {
auto ret = get_weak().lock();
auto ret = getEntry().try_get();
if (!ret) {
LOG(DFATAL) <<
"folly::Singleton<" << getEntry().type().name() <<
......
......@@ -599,40 +599,110 @@ struct BenchmarkSingleton {
int val = 0;
};
BENCHMARK(NormalSingleton, n) {
for (size_t i = 0; i < n; ++i) {
void run4Threads(std::function<void()> f) {
std::vector<std::thread> threads;
for (size_t i = 0; i < 4; ++ i) {
threads.emplace_back(f);
}
for (auto& thread : threads) {
thread.join();
}
}
void normalSingleton(size_t n) {
for (size_t i = 0; i < n; ++ i) {
doNotOptimizeAway(getNormalSingleton());
}
}
BENCHMARK_RELATIVE(MeyersSingleton, n) {
BENCHMARK(NormalSingleton, n) {
normalSingleton(n);
}
BENCHMARK(NormalSingleton4Threads, n) {
run4Threads([=]() {
normalSingleton(n);
});
}
void meyersSingleton(size_t n) {
for (size_t i = 0; i < n; ++i) {
doNotOptimizeAway(getMeyersSingleton());
}
}
BENCHMARK_RELATIVE(MeyersSingleton, n) {
meyersSingleton(n);
}
BENCHMARK_RELATIVE(MeyersSingleton4Threads, n) {
run4Threads([=]() {
meyersSingleton(n);
});
}
struct BenchmarkTag {};
template <typename T, typename Tag = detail::DefaultTag>
using SingletonBenchmark = Singleton <T, Tag, BenchmarkTag>;
struct GetTag{};
struct GetSharedTag{};
struct GetWeakTag{};
SingletonBenchmark<BenchmarkSingleton, GetTag> benchmark_singleton_get;
SingletonBenchmark<BenchmarkSingleton, GetSharedTag>
benchmark_singleton_get_shared;
SingletonBenchmark<BenchmarkSingleton, GetWeakTag> benchmark_singleton_get_weak;
BENCHMARK_RELATIVE(FollySingleton, n) {
void follySingletonRaw(size_t n) {
for (size_t i = 0; i < n; ++i) {
SingletonBenchmark<BenchmarkSingleton, GetTag>::get();
}
}
BENCHMARK_RELATIVE(FollySingletonRaw, n) {
follySingletonRaw(n);
}
BENCHMARK_RELATIVE(FollySingletonRaw4Threads, n) {
run4Threads([=]() {
follySingletonRaw(n);
});
}
void follySingletonSharedPtr(size_t n) {
for (size_t i = 0; i < n; ++i) {
SingletonBenchmark<BenchmarkSingleton, GetTag>::try_get();
SingletonBenchmark<BenchmarkSingleton, GetSharedTag>::try_get();
}
}
BENCHMARK_RELATIVE(FollySingletonWeak, n) {
BENCHMARK_RELATIVE(FollySingletonSharedPtr, n) {
follySingletonSharedPtr(n);
}
BENCHMARK_RELATIVE(FollySingletonSharedPtr4Threads, n) {
run4Threads([=]() {
follySingletonSharedPtr(n);
});
}
void follySingletonWeakPtr(size_t n) {
for (size_t i = 0; i < n; ++i) {
SingletonBenchmark<BenchmarkSingleton, GetWeakTag>::get_weak();
}
}
BENCHMARK_RELATIVE(FollySingletonWeakPtr, n) {
follySingletonWeakPtr(n);
}
BENCHMARK_RELATIVE(FollySingletonWeakPtr4Threads, n) {
run4Threads([=]() {
follySingletonWeakPtr(n);
});
}
int main(int argc, char* argv[]) {
testing::InitGoogleTest(&argc, argv);
google::InitGoogleLogging(argv[0]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment