[PATCH] D121635: [lld][macho][elf] Teach the bump-allocator in lld/Common about thread-safetiness.

Vy Nguyen via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 14 13:31:08 PDT 2022


oontvoo created this revision.
oontvoo added reviewers: int3, MaskRay.
Herald added projects: lld-macho, All.
Herald added a reviewer: lld-macho.
oontvoo requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

The current impl is quite simple: hold a lock briefly while allocating new memory.
(Conceptually the bump-allocator can be implemented without locks using atomic incr', but looking at the current impl, I kind of got discouraged as it seemed too complex)
Performace data: (profiling chromium-framework):

x ./lld_macho_base
+ ./lld_macho_safe_alloc

SYSTEM CPU time:

  N           Min           Max        Median           Avg        Stddev

x   5          0.73          0.83          0.79          0.79   0.037416574
+   5          0.71          0.88          0.77         0.784   0.062689712
No difference proven at 95.0% confidence

USER CPU time:

  N           Min           Max        Median           Avg        Stddev

x   5          3.62          3.73          3.65          3.66   0.043588989
+   5          3.74          3.86          3.84         3.816   0.053665631
Difference at 95.0% confidence
	0.156 +/- 0.0712998
	4.2623% +/- 1.94808%
	(Student's t, pooled s = 0.0488876)

WALL time:

  N           Min           Max        Median           Avg        Stddev

x   5          4.56          4.61          4.59         4.588   0.019235384
+   5          4.68          4.74          4.72         4.714   0.024083189
Difference at 95.0% confidence
	0.126 +/- 0.031786
	2.74629% +/- 0.692808%
	(Student's t, pooled s = 0.0217945)

Use case:
LLD-macho occasionally allocate memory in multiple threads.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D121635

Files:
  lld/Common/Memory.cpp
  lld/MachO/Driver.cpp
  lld/include/lld/Common/Memory.h


Index: lld/include/lld/Common/Memory.h
===================================================================
--- lld/include/lld/Common/Memory.h
+++ lld/include/lld/Common/Memory.h
@@ -22,8 +22,13 @@
 #define LLD_COMMON_MEMORY_H
 
 #include "llvm/Support/Allocator.h"
+#include <mutex>
 
 namespace lld {
+
+// Set to "true" for a thread-safe (but ~2.74% slower) allocator.
+extern bool ThreadSafeAlloc;
+
 // A base class only used by the CommonLinkerContext to keep track of the
 // SpecificAlloc<> instances.
 struct SpecificAllocBase {
@@ -39,6 +44,8 @@
   }
   llvm::SpecificBumpPtrAllocator<T> alloc;
   static int tag;
+
+  std::mutex mutex;
 };
 
 // The address of this static member is only used as a key in
@@ -48,18 +55,35 @@
 // Creates the arena on-demand on the first call; or returns it, if it was
 // already created.
 template <typename T>
-inline llvm::SpecificBumpPtrAllocator<T> &getSpecificAllocSingleton() {
+inline SpecificAlloc<T> *getSpecificAllocSingletonHelper() {
   SpecificAllocBase *instance = SpecificAllocBase::getOrCreate(
       &SpecificAlloc<T>::tag, sizeof(SpecificAlloc<T>),
       alignof(SpecificAlloc<T>), SpecificAlloc<T>::create);
-  return ((SpecificAlloc<T> *)instance)->alloc;
+  return (SpecificAlloc<T> *)instance;
+}
+
+template <typename T>
+inline llvm::SpecificBumpPtrAllocator<T> &getSpecificAllocSingleton() {
+  return getSpecificAllocSingletonHelper<T>()->alloc;
+}
+
+template <typename T> inline T *DoAlloc() {
+  {
+    auto *allocator = getSpecificAllocSingletonHelper<T>();
+    // TODO: maybe make the flag a compile-time config to avoid this branch.
+    if (ThreadSafeAlloc) {
+      std::lock_guard<std::mutex> lock(allocator->mutex);
+      return allocator->alloc.Allocate();
+    } else {
+      return allocator->alloc.Allocate();
+    }
+  }
 }
 
 // Creates new instances of T off a (almost) contiguous arena/object pool. The
 // instances are destroyed whenever lldMain() goes out of scope.
 template <typename T, typename... U> T *make(U &&... args) {
-  return new (getSpecificAllocSingleton<T>().Allocate())
-      T(std::forward<U>(args)...);
+  return new (DoAlloc<T>()) T(std::forward<U>(args)...);
 }
 
 } // namespace lld
Index: lld/MachO/Driver.cpp
===================================================================
--- lld/MachO/Driver.cpp
+++ lld/MachO/Driver.cpp
@@ -1107,6 +1107,7 @@
   if (errorCount())
     return false;
 
+  lld::ThreadSafeAlloc = true;
   if (args.hasArg(OPT_pagezero_size)) {
     uint64_t pagezeroSize = args::getHex(args, OPT_pagezero_size, 0);
 
Index: lld/Common/Memory.cpp
===================================================================
--- lld/Common/Memory.cpp
+++ lld/Common/Memory.cpp
@@ -12,6 +12,8 @@
 using namespace llvm;
 using namespace lld;
 
+bool lld::ThreadSafeAlloc = false;
+
 SpecificAllocBase *
 lld::SpecificAllocBase::getOrCreate(void *tag, size_t size, size_t align,
                                     SpecificAllocBase *(&creator)(void *)) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D121635.415200.patch
Type: text/x-patch
Size: 2984 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220314/6734b2ba/attachment.bin>


More information about the llvm-commits mailing list