[lld] r194666 - Avoid parsing large YAML file.

Rui Ueyama ruiu at google.com
Wed Nov 13 21:57:54 PST 2013


Author: ruiu
Date: Wed Nov 13 23:57:54 2013
New Revision: 194666

URL: http://llvm.org/viewvc/llvm-project?rev=194666&view=rev
Log:
Avoid parsing large YAML file.

YAML files tend to be very large compared to binary formats because of ASCII
format inefficiency. And the YAML reader consumes an excessively large amount
of memory when parsing a large file. It's very slow too.

For example, I observed that 6MB executable became 120MB YAML file, and the
YAML reader consumed more than 1.5GB memory to load it. The YAML reader even
caused OOM error on 32 bit, causing the entire process to fail.

This patch sets the limit on the YAML file size the linker will try to load in
the RoundTripYAML test as a safeguard.

Modified:
    lld/trunk/lib/Passes/RoundTripYAMLPass.cpp

Modified: lld/trunk/lib/Passes/RoundTripYAMLPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Passes/RoundTripYAMLPass.cpp?rev=194666&r1=194665&r2=194666&view=diff
==============================================================================
--- lld/trunk/lib/Passes/RoundTripYAMLPass.cpp (original)
+++ lld/trunk/lib/Passes/RoundTripYAMLPass.cpp Wed Nov 13 23:57:54 2013
@@ -15,6 +15,11 @@
 
 #include "llvm/Support/Path.h"
 
+// Skip YAML files larger than this to avoid OOM error. The YAML reader consumes
+// excessively large amount of memory when parsing a large file.
+// TODO: Fix the YAML reader to reduce memory footprint.
+static const size_t MAX_YAML_FILE_SIZE = 50 * 1024 * 1024;
+
 using namespace lld;
 
 /// Perform the actual pass
@@ -34,10 +39,11 @@ void RoundTripYAMLPass::perform(std::uni
   if (MemoryBuffer::getFileOrSTDIN(tmpYAMLFile.str(), buff))
     return;
 
-  std::unique_ptr<MemoryBuffer> mb(buff.take());
-  _context.getYAMLReader().parseFile(mb, _yamlFile);
-
-  mergedFile.reset(new FileToMutable(_context, *_yamlFile[0].get()));
+  if (buff->getBufferSize() < MAX_YAML_FILE_SIZE) {
+    std::unique_ptr<MemoryBuffer> mb(buff.take());
+    _context.getYAMLReader().parseFile(mb, _yamlFile);
+    mergedFile.reset(new FileToMutable(_context, *_yamlFile[0].get()));
+  }
 
   llvm::sys::fs::remove(tmpYAMLFile.str());
 }





More information about the llvm-commits mailing list