From 64faafba19621087b060d577c36bbcf6041cb4b6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 16 Dec 2013 20:58:21 -0800 Subject: rustc: Optimize reading metadata by 4x We were previously reading metadata via `ar p`, but as learned from rustdoc awhile back, spawning a process to do something is pretty slow. Turns out LLVM has an Archive class to read archives, but it cannot write archives. This commits adds bindings to the read-only version of the LLVM archive class (with a new type that only has a read() method), and then it uses this class when reading the metadata out of rlibs. When you put this in tandem of not compressing the metadata, reading the metadata is 4x faster than it used to be The timings I got for reading metadata from the respective libraries was: libstd-04ff901e-0.9-pre.dylib => 100ms libstd-04ff901e-0.9-pre.rlib => 23ms librustuv-7945354c-0.9-pre.dylib => 4ms librustuv-7945354c-0.9-pre.rlib => 1ms librustc-5b94a16f-0.9-pre.dylib => 87ms librustc-5b94a16f-0.9-pre.rlib => 35ms libextra-a6ebb16f-0.9-pre.dylib => 63ms libextra-a6ebb16f-0.9-pre.rlib => 15ms libsyntax-2e4c0458-0.9-pre.dylib => 86ms libsyntax-2e4c0458-0.9-pre.rlib => 22ms In order to always take advantage of these faster metadata read-times, I sort the files in filesearch based on whether they have an rlib extension or not (prefer all rlib files first). Overall, this halved the compile time for a `fn main() {}` crate from 0.185s to 0.095s on my system (when preferring dynamic linking). Reading metadata is still the slowest pass of the compiler at 0.035s, but it's getting pretty close to linking at 0.021s! The next best optimization is to just not copy the metadata from LLVM because that's the most expensive part of reading metadata right now. --- src/rustllvm/RustWrapper.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'src/rustllvm/RustWrapper.cpp') diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index fb611dd15c2..d66f90a5352 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -9,6 +9,7 @@ // except according to those terms. #include "rustllvm.h" +#include "llvm/Object/Archive.h" //===----------------------------------------------------------------------=== // @@ -19,6 +20,7 @@ using namespace llvm; using namespace llvm::sys; +using namespace llvm::object; const char *LLVMRustError; @@ -558,3 +560,41 @@ LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) { } return true; } + +extern "C" void* +LLVMRustOpenArchive(char *path) { + OwningPtr buf; + error_code err = MemoryBuffer::getFile(path, buf); + if (err) { + LLVMRustError = err.message().c_str(); + return NULL; + } + Archive *ret = new Archive(buf.take(), err); + if (err) { + LLVMRustError = err.message().c_str(); + return NULL; + } + return ret; +} + +extern "C" const char* +LLVMRustArchiveReadSection(Archive *ar, char *name, size_t *size) { + for (Archive::child_iterator child = ar->begin_children(), + end = ar->end_children(); + child != end; ++child) { + StringRef sect_name; + error_code err = child->getName(sect_name); + if (err) continue; + if (sect_name.trim(" ") == name) { + StringRef buf = child->getBuffer(); + *size = buf.size(); + return buf.data(); + } + } + return NULL; +} + +extern "C" void +LLVMRustDestroyArchive(Archive *ar) { + delete ar; +} -- cgit 1.4.1-3-g733a5