From: Yedidya Feldblum Date: Thu, 18 Jan 2018 22:49:00 +0000 (-0800) Subject: Improve SingletonThreadLocal performance X-Git-Tag: v2018.01.22.00~16 X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=commitdiff_plain;h=6374f552672fe630d7060937593c1982be448b87 Improve SingletonThreadLocal performance Summary: [Folly] Improve `SingletonThreadLocal` performance. By explicitly controlling inlining behavior. The ctor is definitionally cold - once per process - so outline. `get` is hot so inline. Uncached `get` is cold - once per thread - so outline uncached. Reviewed By: djwatson Differential Revision: D6736662 fbshipit-source-id: 4cd77c7772b46e2e3c6b2a3dc071b2b06522979e --- diff --git a/folly/SingletonThreadLocal.h b/folly/SingletonThreadLocal.h index 69249564..3add4fef 100644 --- a/folly/SingletonThreadLocal.h +++ b/folly/SingletonThreadLocal.h @@ -43,29 +43,29 @@ class SingletonThreadLocal { SingletonThreadLocal() : SingletonThreadLocal([]() { return new T(); }) {} - explicit SingletonThreadLocal(CreateFunc createFunc) - : singleton_([createFunc = std::move(createFunc)]() mutable { - return new ThreadLocalT([createFunc = - std::move(createFunc)]() mutable { - return new Wrapper(std::unique_ptr(createFunc())); + template + FOLLY_NOINLINE explicit SingletonThreadLocal(Create create) + : singleton_([create = std::move(create)]() mutable { + return new ThreadLocalT([create = std::move(create)]() mutable { + return new Wrapper(std::unique_ptr(create())); }); }) {} - static T& get() { + FOLLY_ALWAYS_INLINE static T& get() { #ifdef FOLLY_TLS - if (UNLIKELY(*localPtr() == nullptr)) { - *localPtr() = &(**SingletonT::get()); - } - - return **localPtr(); + return *localPtr() ? **localPtr() : *(*localPtr() = &getSlow()); #else return **SingletonT::get(); #endif } private: + FOLLY_NOINLINE static T& getSlow() { + return **SingletonT::get(); + } + #ifdef FOLLY_TLS - static T** localPtr() { + FOLLY_ALWAYS_INLINE static T** localPtr() { static FOLLY_TLS T* localPtr = nullptr; return &localPtr; }