[PATCH] D69294: [LLD][ELF] Support -[no-]mmap-output-file

Nick Terrell via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 21 20:50:22 PDT 2019


terrelln created this revision.
terrelln added reviewers: ruiu, MaskRay.
Herald added subscribers: arichardson, emaste.
Herald added a reviewer: espindola.
Herald added a project: LLVM.
terrelln added a parent revision: D69293: [Support] Add in memory flag for FileOutputBuffer.

Add support for -[no-]mmap-output-file to ELF. LLD currently explicitly
ignores this flag for compatibility with the GNU linker.

We need this flag to speed up link time for large binaries in certain
scenarios. When mmaping a large output file on a BtrFS filesystem and
the system is under memory pressure BtrFS will flush dirty pages before
the output buffer is unmapped. This is normally okay, since BtrFS will
flush 4KB pages. However, when BtrFS compression is enabled, BtrFS
writes 128KB blocks. Since LLD doesn't write the output file
sequentially, this causes massive write and compression amplification.
We've observed 3-5x faster builds with -no-mmap-output-file when we hit
this scenario.

Silently ignoring -no-mmap-output-file caused a silent regression when
we switched from gold to lld. We pass -no-mmap-output-file to fix this
edge case, but since lld silently ignored the flag we didn't realize it
wasn't being respected.

Test Plan:

  ninja check-lld

Benchmark building a 9 GB binary that exposes this edge case. I linked 3
times with -mmap-output-file and 3 times with -no-mmap-output-file and
took the average. The machine has 24 cores @ 2.4 GHz, 112 GB of RAM,
BtrFS mounted with -compress-force=zstd, and an 80% full disk.

| Mode    | Time  |
| ------- | ----- |
| mmap    | 894 s |
| no mmap | 126 s |
|

I was unable to reproduce the regression with any binaries in
lld-speed-test. I suspect the BtrFS flushing will only happen when the
output file is large and the system is under memory pressure.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D69294

Files:
  lld/ELF/Config.h
  lld/ELF/Driver.cpp
  lld/ELF/Options.td
  lld/ELF/Writer.cpp
  lld/test/ELF/mmap-output-file.s
  lld/test/ELF/silent-ignore.test


Index: lld/test/ELF/silent-ignore.test
===================================================================
--- lld/test/ELF/silent-ignore.test
+++ lld/test/ELF/silent-ignore.test
@@ -6,7 +6,6 @@
 RUN:   -no-copy-dt-needed-entries \
 RUN:   -no-ctors-in-init-array \
 RUN:   -no-keep-memory \
-RUN:   -no-mmap-output-file \
 RUN:   -no-pipeline-knowledge \
 RUN:   -no-warn-mismatch \
 RUN:   -p \
Index: lld/test/ELF/mmap-output-file.s
===================================================================
--- /dev/null
+++ lld/test/ELF/mmap-output-file.s
@@ -0,0 +1,14 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -mmap-output-file -o %t1
+# RUN: llvm-objdump -d %t1 | FileCheck %s
+
+# CHECK: nop
+
+# RUN: ld.lld %t.o -no-mmap-output-file -o %t2
+# RUN: diff %t1 %t2
+
+.globl _start
+_start:
+  nop
Index: lld/ELF/Writer.cpp
===================================================================
--- lld/ELF/Writer.cpp
+++ lld/ELF/Writer.cpp
@@ -2594,6 +2594,8 @@
   unsigned flags = 0;
   if (!config->relocatable)
     flags = FileOutputBuffer::F_executable;
+  if (!config->mmapOutputFile)
+    flags |= FileOutputBuffer::F_in_memory;
   Expected<std::unique_ptr<FileOutputBuffer>> bufferOrErr =
       FileOutputBuffer::create(config->outputFile, fileSize, flags);
 
Index: lld/ELF/Options.td
===================================================================
--- lld/ELF/Options.td
+++ lld/ELF/Options.td
@@ -406,6 +406,10 @@
     "Warn about problems with the symbol ordering file (default)",
     "Do not warn about problems with the symbol ordering file">;
 
+defm mmap_output_file: B<"mmap-output-file",
+    "Map the output file for writing (default)",
+    "Do not map the output file for writing">;
+
 def warn_unresolved_symbols: F<"warn-unresolved-symbols">,
   HelpText<"Report unresolved symbols as warnings">;
 
@@ -566,7 +570,6 @@
 def: F<"no-copy-dt-needed-entries">;
 def: F<"no-ctors-in-init-array">;
 def: F<"no-keep-memory">;
-def: F<"no-mmap-output-file">;
 def: F<"no-pipeline-knowledge">;
 def: F<"no-warn-mismatch">;
 def: Flag<["-"], "p">;
Index: lld/ELF/Driver.cpp
===================================================================
--- lld/ELF/Driver.cpp
+++ lld/ELF/Driver.cpp
@@ -947,6 +947,8 @@
       args.hasFlag(OPT_warn_ifunc_textrel, OPT_no_warn_ifunc_textrel, false);
   config->warnSymbolOrdering =
       args.hasFlag(OPT_warn_symbol_ordering, OPT_no_warn_symbol_ordering, true);
+  config->mmapOutputFile =
+      args.hasFlag(OPT_mmap_output_file, OPT_no_mmap_output_file, true);
   config->zCombreloc = getZFlag(args, "combreloc", "nocombreloc", true);
   config->zCopyreloc = getZFlag(args, "copyreloc", "nocopyreloc", true);
   config->zExecstack = getZFlag(args, "execstack", "noexecstack", false);
Index: lld/ELF/Config.h
===================================================================
--- lld/ELF/Config.h
+++ lld/ELF/Config.h
@@ -196,6 +196,7 @@
   bool warnMissingEntry;
   bool warnSymbolOrdering;
   bool writeAddends;
+  bool mmapOutputFile;
   bool zCombreloc;
   bool zCopyreloc;
   bool zExecstack;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D69294.225990.patch
Type: text/x-patch
Size: 3127 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20191022/6dc7247d/attachment.bin>


More information about the llvm-commits mailing list