From faa75f83a86b59f9107d244b568137ddc4270f8a Mon Sep 17 00:00:00 2001 From: Andrii Grynenko Date: Tue, 20 Oct 2015 19:34:57 -0700 Subject: [PATCH] Improve folly::Singleton try_get perf and bring back raw get benchmark Reviewed By: elsteveogrande Differential Revision: D2517522 fb-gh-sync-id: eab11d17ce5db94e09aa733b6067e44d36be6345 --- folly/Singleton-inl.h | 16 ++++++- folly/Singleton.h | 3 +- folly/test/SingletonTest.cpp | 82 +++++++++++++++++++++++++++++++++--- 3 files changed, 92 insertions(+), 9 deletions(-) diff --git a/folly/Singleton-inl.h b/folly/Singleton-inl.h index e946e8a5..deca4b2c 100644 --- a/folly/Singleton-inl.h +++ b/folly/Singleton-inl.h @@ -76,7 +76,8 @@ void SingletonHolder::registerSingletonMock(CreateFunc c, TeardownFunc t) { template T* SingletonHolder::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::get() { template std::weak_ptr SingletonHolder::get_weak() { - if (UNLIKELY(state_ != SingletonHolderState::Living)) { + if (UNLIKELY(state_.load(std::memory_order_acquire) != + SingletonHolderState::Living)) { createInstance(); } return instance_weak_; } +template +std::shared_ptr SingletonHolder::try_get() { + if (UNLIKELY(state_.load(std::memory_order_acquire) != + SingletonHolderState::Living)) { + createInstance(); + } + + return instance_weak_.lock(); +} + template TypeDescriptor SingletonHolder::type() { return type_; diff --git a/folly/Singleton.h b/folly/Singleton.h index 01e0bed5..194eb6b4 100644 --- a/folly/Singleton.h +++ b/folly/Singleton.h @@ -243,6 +243,7 @@ struct SingletonHolder : public SingletonHolderBase { inline T* get(); inline std::weak_ptr get_weak(); + inline std::shared_ptr 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 try_get() { - auto ret = get_weak().lock(); + auto ret = getEntry().try_get(); if (!ret) { LOG(DFATAL) << "folly::Singleton<" << getEntry().type().name() << diff --git a/folly/test/SingletonTest.cpp b/folly/test/SingletonTest.cpp index da62e18f..575e136f 100644 --- a/folly/test/SingletonTest.cpp +++ b/folly/test/SingletonTest.cpp @@ -599,40 +599,110 @@ struct BenchmarkSingleton { int val = 0; }; -BENCHMARK(NormalSingleton, n) { - for (size_t i = 0; i < n; ++i) { +void run4Threads(std::function f) { + std::vector 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 using SingletonBenchmark = Singleton ; struct GetTag{}; +struct GetSharedTag{}; struct GetWeakTag{}; SingletonBenchmark benchmark_singleton_get; +SingletonBenchmark +benchmark_singleton_get_shared; SingletonBenchmark benchmark_singleton_get_weak; -BENCHMARK_RELATIVE(FollySingleton, n) { +void follySingletonRaw(size_t n) { + for (size_t i = 0; i < n; ++i) { + SingletonBenchmark::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::try_get(); + SingletonBenchmark::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::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]); -- 2.34.1