FYI patch: using write to output the file

Rafael EspĂ­ndola via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 8 15:15:16 PST 2016


The attached patch changes lld to use posix_memalign + write instead of mmap.

When linking "small" binaries like clang there is almost no
difference. When linking scylladb I get a 1.019X slowdown when writing
to tmpfs and a 1.040 speedup when writing to btrfs.

At this stage I would say this just shows there is potential, but we
have to at least benchmark this on a few filesystems.

It would also be interesting to try doing one write for each section.

Cheers,
Rafael
-------------- next part --------------
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index 0dca801..d1ae695 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -21,6 +21,12 @@
 #include "llvm/Support/StringSaver.h"
 #include "llvm/Support/raw_ostream.h"
 
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <unistd.h>
+
 using namespace llvm;
 using namespace llvm::ELF;
 using namespace llvm::object;
@@ -72,9 +78,9 @@ private:
   void assignAddresses();
   void assignAddressesRelocatable();
   void fixAbsoluteSymbols();
-  bool openFile();
   void writeHeader();
   void writeSections();
+  void writeFile();
   bool isDiscarded(InputSectionBase<ELFT> *IS) const;
   StringRef getOutputSectionName(InputSectionBase<ELFT> *S) const;
   bool needsInterpSection() const {
@@ -88,7 +94,7 @@ private:
   void addCommonSymbols(std::vector<DefinedCommon *> &Syms);
   void addCopyRelSymbols(std::vector<SharedSymbol<ELFT> *> &Syms);
 
-  std::unique_ptr<llvm::FileOutputBuffer> Buffer;
+  std::unique_ptr<uint8_t[]> Buffer;
 
   BumpPtrAllocator Alloc;
   std::vector<OutputSectionBase<ELFT> *> OutputSections;
@@ -215,13 +221,16 @@ template <class ELFT> void Writer<ELFT>::run() {
     assignAddressesRelocatable();
   }
   fixAbsoluteSymbols();
-  if (!openFile())
-    return;
+  void *Ptr;
+  int R = posix_memalign(&Ptr, 4096, FileSize);
+  assert(R == 0);
+  Buffer.reset((uint8_t *)Ptr);
+  memset(Buffer.get(), 0, FileSize);
   writeHeader();
   writeSections();
   if (HasError)
     return;
-  check(Buffer->commit());
+  writeFile();
 }
 
 namespace {
@@ -1495,8 +1504,20 @@ template <class ELFT> void Writer<ELFT>::fixAbsoluteSymbols() {
   }
 }
 
+template <class ELFT> void Writer<ELFT>::writeFile() {
+  // FIXME: use a temp file
+  int FD = open(std::string(Config->OutputFile).c_str(), O_WRONLY | O_CREAT,
+                S_IRWXU);
+  if (FD == -1)
+    fatal("failed to open " + Config->OutputFile);
+  int R = ftruncate(FD, FileSize);
+  assert(R == 0);
+  ssize_t Ret = ::write(FD, Buffer.get(), FileSize);
+  assert(Ret == (ssize_t)FileSize);
+}
+
 template <class ELFT> void Writer<ELFT>::writeHeader() {
-  uint8_t *Buf = Buffer->getBufferStart();
+  uint8_t *Buf = Buffer.get();
   memcpy(Buf, "\177ELF", 4);
 
   auto &FirstObj = cast<ELFFileBase<ELFT>>(*Config->FirstElf);
@@ -1535,19 +1556,9 @@ template <class ELFT> void Writer<ELFT>::writeHeader() {
     Sec->writeHeaderTo(++SHdrs);
 }
 
-template <class ELFT> bool Writer<ELFT>::openFile() {
-  ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
-      FileOutputBuffer::create(Config->OutputFile, FileSize,
-                               FileOutputBuffer::F_executable);
-  if (error(BufferOrErr, "failed to open " + Config->OutputFile))
-    return false;
-  Buffer = std::move(*BufferOrErr);
-  return true;
-}
-
 // Write section contents to a mmap'ed file.
 template <class ELFT> void Writer<ELFT>::writeSections() {
-  uint8_t *Buf = Buffer->getBufferStart();
+  uint8_t *Buf = Buffer.get();
 
   // PPC64 needs to process relocations in the .opd section before processing
   // relocations in code-containing sections.


More information about the llvm-commits mailing list