[PATCH] D32881: Read public symbol names for LazyObjectFiles in parallel.
Rafael Avila de Espindola via llvm-commits
llvm-commits at lists.llvm.org
Thu May 4 14:21:16 PDT 2017
Interesting. I will try benchmarking this tomorrow.
Rui Ueyama via Phabricator <reviews at reviews.llvm.org> writes:
> ruiu created this revision.
>
> This is in the context of https://reviews.llvm.org/D32867 and
> attempts to speed up symbols from object files in archive files.
>
> Interestingly, archives without symbol tables is faster than those
> with symbol tables with this patch. I benchmarked the linker with
> the default build configuration, stripped symbol tables from archives
> in the build tree, and run the same test again. The first attempt
> to link chrome took 8.17s (average of 10 trials using the perf
> command). The second attempt took 8.04s. This is odd but seems real.
>
> Somewhat orthogonal to this patch, but that result seems to imply
> that there's room for improvements in the code to handle archive
> symbol table.
>
>
> https://reviews.llvm.org/D32881
>
> Files:
> lld/ELF/Driver.cpp
> lld/ELF/InputFiles.cpp
> lld/ELF/InputFiles.h
>
>
> Index: lld/ELF/InputFiles.h
> ===================================================================
> --- lld/ELF/InputFiles.h
> +++ lld/ELF/InputFiles.h
> @@ -226,15 +226,18 @@
> }
>
> template <class ELFT> void parse();
> + void readSymbols();
> MemoryBufferRef getBuffer();
> InputFile *fetch();
>
> private:
> std::vector<StringRef> getSymbols();
> template <class ELFT> std::vector<StringRef> getElfSymbols();
> std::vector<StringRef> getBitcodeSymbols();
>
> + llvm::Optional<std::vector<StringRef>> Symbols;
> bool Seen = false;
> + llvm::BumpPtrAllocator Alloc;
> };
>
> // An ArchiveFile object represents a .a file.
> Index: lld/ELF/InputFiles.cpp
> ===================================================================
> --- lld/ELF/InputFiles.cpp
> +++ lld/ELF/InputFiles.cpp
> @@ -984,8 +984,11 @@
> return createObjectFile(MBRef);
> }
>
> +void LazyObjectFile::readSymbols() { Symbols = getSymbols(); }
> +
> template <class ELFT> void LazyObjectFile::parse() {
> - for (StringRef Sym : getSymbols())
> + assert(Symbols.hasValue());
> + for (StringRef Sym : *Symbols)
> Symtab<ELFT>::X->addLazyObject(Sym, *this);
> }
>
> @@ -1004,8 +1007,8 @@
> uint32_t FirstNonLocal = Sec.sh_info;
> StringRef StringTable =
> check(Obj.getStringTableForSymtab(Sec, Sections), toString(this));
> - std::vector<StringRef> V;
>
> + std::vector<StringRef> V;
> for (const Elf_Sym &Sym : Syms.slice(FirstNonLocal))
> if (Sym.st_shndx != SHN_UNDEF)
> V.push_back(check(Sym.getName(StringTable), toString(this)));
> @@ -1017,6 +1020,11 @@
> std::vector<StringRef> LazyObjectFile::getBitcodeSymbols() {
> std::unique_ptr<lto::InputFile> Obj =
> check(lto::InputFile::create(this->MB), toString(this));
> +
> + // Since this function is called inside parallel_for,
> + // we want to use per-object allocator.
> + StringSaver Saver(Alloc);
> +
> std::vector<StringRef> V;
> for (const lto::InputFile::Symbol &Sym : Obj->symbols())
> if (!Sym.isUndefined())
> Index: lld/ELF/Driver.cpp
> ===================================================================
> --- lld/ELF/Driver.cpp
> +++ lld/ELF/Driver.cpp
> @@ -319,6 +319,18 @@
> return Default;
> }
>
> +// We need to call readSymbols() on each LazyObjectFile to let it
> +// construct per-file internal data structure. Do that in parallel.
> +static void readLazyObjects(ArrayRef<InputFile *> Files) {
> + std::vector<LazyObjectFile *> V;
> + for (InputFile *F : Files)
> + if (auto *Lazy = dyn_cast<LazyObjectFile>(F))
> + V.push_back(Lazy);
> +
> + parallelForEach(V.begin(), V.end(),
> + [](LazyObjectFile *F) { F->readSymbols(); });
> +}
> +
> void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) {
> ELFOptTable Parser;
> opt::InputArgList Args = Parser.parse(ArgsArr.slice(1));
> @@ -380,6 +392,7 @@
> inferMachineType();
> setConfigs();
> checkOptions(Args);
> + readLazyObjects(Files);
> if (ErrorCount)
> return;
>
>
>
> Index: lld/ELF/InputFiles.h
> ===================================================================
> --- lld/ELF/InputFiles.h
> +++ lld/ELF/InputFiles.h
> @@ -226,15 +226,18 @@
> }
>
> template <class ELFT> void parse();
> + void readSymbols();
> MemoryBufferRef getBuffer();
> InputFile *fetch();
>
> private:
> std::vector<StringRef> getSymbols();
> template <class ELFT> std::vector<StringRef> getElfSymbols();
> std::vector<StringRef> getBitcodeSymbols();
>
> + llvm::Optional<std::vector<StringRef>> Symbols;
> bool Seen = false;
> + llvm::BumpPtrAllocator Alloc;
> };
>
> // An ArchiveFile object represents a .a file.
> Index: lld/ELF/InputFiles.cpp
> ===================================================================
> --- lld/ELF/InputFiles.cpp
> +++ lld/ELF/InputFiles.cpp
> @@ -984,8 +984,11 @@
> return createObjectFile(MBRef);
> }
>
> +void LazyObjectFile::readSymbols() { Symbols = getSymbols(); }
> +
> template <class ELFT> void LazyObjectFile::parse() {
> - for (StringRef Sym : getSymbols())
> + assert(Symbols.hasValue());
> + for (StringRef Sym : *Symbols)
> Symtab<ELFT>::X->addLazyObject(Sym, *this);
> }
>
> @@ -1004,8 +1007,8 @@
> uint32_t FirstNonLocal = Sec.sh_info;
> StringRef StringTable =
> check(Obj.getStringTableForSymtab(Sec, Sections), toString(this));
> - std::vector<StringRef> V;
>
> + std::vector<StringRef> V;
> for (const Elf_Sym &Sym : Syms.slice(FirstNonLocal))
> if (Sym.st_shndx != SHN_UNDEF)
> V.push_back(check(Sym.getName(StringTable), toString(this)));
> @@ -1017,6 +1020,11 @@
> std::vector<StringRef> LazyObjectFile::getBitcodeSymbols() {
> std::unique_ptr<lto::InputFile> Obj =
> check(lto::InputFile::create(this->MB), toString(this));
> +
> + // Since this function is called inside parallel_for,
> + // we want to use per-object allocator.
> + StringSaver Saver(Alloc);
> +
> std::vector<StringRef> V;
> for (const lto::InputFile::Symbol &Sym : Obj->symbols())
> if (!Sym.isUndefined())
> Index: lld/ELF/Driver.cpp
> ===================================================================
> --- lld/ELF/Driver.cpp
> +++ lld/ELF/Driver.cpp
> @@ -319,6 +319,18 @@
> return Default;
> }
>
> +// We need to call readSymbols() on each LazyObjectFile to let it
> +// construct per-file internal data structure. Do that in parallel.
> +static void readLazyObjects(ArrayRef<InputFile *> Files) {
> + std::vector<LazyObjectFile *> V;
> + for (InputFile *F : Files)
> + if (auto *Lazy = dyn_cast<LazyObjectFile>(F))
> + V.push_back(Lazy);
> +
> + parallelForEach(V.begin(), V.end(),
> + [](LazyObjectFile *F) { F->readSymbols(); });
> +}
> +
> void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) {
> ELFOptTable Parser;
> opt::InputArgList Args = Parser.parse(ArgsArr.slice(1));
> @@ -380,6 +392,7 @@
> inferMachineType();
> setConfigs();
> checkOptions(Args);
> + readLazyObjects(Files);
> if (ErrorCount)
> return;
>
More information about the llvm-commits
mailing list