Improve SingletonThreadLocal performance
authorYedidya Feldblum <yfeldblum@fb.com>
Thu, 18 Jan 2018 22:49:00 +0000 (14:49 -0800)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Thu, 18 Jan 2018 23:12:30 +0000 (15:12 -0800)
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

folly/SingletonThreadLocal.h

index 6924956..3add4fe 100644 (file)
@@ -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<T>(createFunc()));
+  template <typename Create>
+  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<T>(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;
   }