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) { ...@@ -76,7 +76,8 @@ void SingletonHolder<T>::registerSingletonMock(CreateFunc c, TeardownFunc t) {
template <typename T> template <typename T>
T* SingletonHolder<T>::get() { T* SingletonHolder<T>::get() {
if (LIKELY(state_ == SingletonHolderState::Living)) { if (LIKELY(state_.load(std::memory_order_acquire) ==
SingletonHolderState::Living)) {
return instance_ptr_; return instance_ptr_;
} }
createInstance(); createInstance();
...@@ -93,13 +94,24 @@ T* SingletonHolder<T>::get() { ...@@ -93,13 +94,24 @@ T* SingletonHolder<T>::get() {
template <typename T> template <typename T>
std::weak_ptr<T> SingletonHolder<T>::get_weak() { std::weak_ptr<T> SingletonHolder<T>::get_weak() {
if (UNLIKELY(state_ != SingletonHolderState::Living)) { if (UNLIKELY(state_.load(std::memory_order_acquire) !=
SingletonHolderState::Living)) {
createInstance(); createInstance();
} }
return instance_weak_; 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> template <typename T>
TypeDescriptor SingletonHolder<T>::type() { TypeDescriptor SingletonHolder<T>::type() {
return type_; return type_;
......
...@@ -243,6 +243,7 @@ struct SingletonHolder : public SingletonHolderBase { ...@@ -243,6 +243,7 @@ struct SingletonHolder : public SingletonHolderBase {
inline T* get(); inline T* get();
inline std::weak_ptr<T> get_weak(); inline std::weak_ptr<T> get_weak();
inline std::shared_ptr<T> try_get();
void registerSingleton(CreateFunc c, TeardownFunc t); void registerSingleton(CreateFunc c, TeardownFunc t);
void registerSingletonMock(CreateFunc c, TeardownFunc t); void registerSingletonMock(CreateFunc c, TeardownFunc t);
...@@ -494,7 +495,7 @@ class Singleton { ...@@ -494,7 +495,7 @@ class Singleton {
// Avoid holding these shared_ptrs beyond the scope of a function; // Avoid holding these shared_ptrs beyond the scope of a function;
// don't put them in member variables, always use try_get() instead // don't put them in member variables, always use try_get() instead
static std::shared_ptr<T> try_get() { static std::shared_ptr<T> try_get() {
auto ret = get_weak().lock(); auto ret = getEntry().try_get();
if (!ret) { if (!ret) {
LOG(DFATAL) << LOG(DFATAL) <<
"folly::Singleton<" << getEntry().type().name() << "folly::Singleton<" << getEntry().type().name() <<
......
...@@ -599,40 +599,110 @@ struct BenchmarkSingleton { ...@@ -599,40 +599,110 @@ struct BenchmarkSingleton {
int val = 0; int val = 0;
}; };
BENCHMARK(NormalSingleton, n) { void run4Threads(std::function<void()> f) {
for (size_t i = 0; i < n; ++i) { 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()); 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) { for (size_t i = 0; i < n; ++i) {
doNotOptimizeAway(getMeyersSingleton()); doNotOptimizeAway(getMeyersSingleton());
} }
} }
BENCHMARK_RELATIVE(MeyersSingleton, n) {
meyersSingleton(n);
}
BENCHMARK_RELATIVE(MeyersSingleton4Threads, n) {
run4Threads([=]() {
meyersSingleton(n);
});
}
struct BenchmarkTag {}; struct BenchmarkTag {};
template <typename T, typename Tag = detail::DefaultTag> template <typename T, typename Tag = detail::DefaultTag>
using SingletonBenchmark = Singleton <T, Tag, BenchmarkTag>; using SingletonBenchmark = Singleton <T, Tag, BenchmarkTag>;
struct GetTag{}; struct GetTag{};
struct GetSharedTag{};
struct GetWeakTag{}; struct GetWeakTag{};
SingletonBenchmark<BenchmarkSingleton, GetTag> benchmark_singleton_get; SingletonBenchmark<BenchmarkSingleton, GetTag> benchmark_singleton_get;
SingletonBenchmark<BenchmarkSingleton, GetSharedTag>
benchmark_singleton_get_shared;
SingletonBenchmark<BenchmarkSingleton, GetWeakTag> benchmark_singleton_get_weak; 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) { 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) { for (size_t i = 0; i < n; ++i) {
SingletonBenchmark<BenchmarkSingleton, GetWeakTag>::get_weak(); SingletonBenchmark<BenchmarkSingleton, GetWeakTag>::get_weak();
} }
} }
BENCHMARK_RELATIVE(FollySingletonWeakPtr, n) {
follySingletonWeakPtr(n);
}
BENCHMARK_RELATIVE(FollySingletonWeakPtr4Threads, n) {
run4Threads([=]() {
follySingletonWeakPtr(n);
});
}
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
testing::InitGoogleTest(&argc, argv); testing::InitGoogleTest(&argc, argv);
google::InitGoogleLogging(argv[0]); 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