diff options
author | Reid Kleckner <rnk@google.com> | 2018-11-27 19:00:23 +0000 |
---|---|---|
committer | Reid Kleckner <rnk@google.com> | 2018-11-27 19:00:23 +0000 |
commit | 36cff6306ac698d5bb1941aa5a0ec23c04de120a (patch) | |
tree | 27bf49cfdc143579a1eff5976faa0da28f905388 /lib/DebugInfo | |
parent | 6c99d2be100317539e2e462be96b3acd2c56e60b (diff) | |
download | llvm-36cff6306ac698d5bb1941aa5a0ec23c04de120a.tar.gz |
[PDB] Add symbol records in bulk
Summary:
This speeds up linking clang.exe/pdb with /DEBUG:GHASH by 31%, from
12.9s to 9.8s.
Symbol records are typically small (16.7 bytes on average), but we
processed them one at a time. CVSymbol is a relatively "large" type. It
wraps an ArrayRef<uint8_t> with a kind an optional 32-bit hash, which we
don't need. Before this change, each DbiModuleDescriptorBuilder would
maintain an array of CVSymbols, and would write them individually with a
BinaryItemStream.
With this change, we now add symbols that happen to appear contiguously
in bulk. For each .debug$S section (roughly one per function), we
allocate two copies, one for relocation, and one for realignment
purposes. For runs of symbols that go in the module stream, which is
most symbols, we now add them as a single ArrayRef<uint8_t>, so the
vector DbiModuleDescriptorBuilder is roughly linear in the number of
.debug$S sections (O(# funcs)) instead of the number of symbol records
(very large).
Some stats on symbol sizes for the curious:
PDB size: 507M
sym bytes: 316,508,016
sym count: 18,954,971
sym byte avg: 16.7
As future work, we may be able to skip copying symbol records in the
linker for realignment purposes if we make LLVM write them aligned into
the object file. We need to double check that such symbol records are
still compatible with link.exe, but if so, it's definitely worth doing,
since my profile shows we spend 500ms in memcpy in the symbol merging
code. We could potentially cut that in half by saving a copy.
Alternatively, we could apply the relocations *after* we iterate the
symbols. This would require some careful re-engineering of the
relocation processing code, though.
Reviewers: zturner, aganea, ruiu
Subscribers: hiraditya, llvm-commits
Differential Revision: https://reviews.llvm.org/D54554
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@347687 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/DebugInfo')
-rw-r--r-- | lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp | 30 |
1 files changed, 17 insertions, 13 deletions
diff --git a/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp index b97f1e90bcf..12df042c4eb 100644 --- a/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp @@ -19,7 +19,6 @@ #include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h" #include "llvm/DebugInfo/PDB/Native/RawConstants.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" -#include "llvm/Support/BinaryItemStream.h" #include "llvm/Support/BinaryStreamWriter.h" using namespace llvm; @@ -66,12 +65,22 @@ void DbiModuleDescriptorBuilder::setFirstSectionContrib( } void DbiModuleDescriptorBuilder::addSymbol(CVSymbol Symbol) { - Symbols.push_back(Symbol); - // Symbols written to a PDB file are required to be 4 byte aligned. The same + // Defer to the bulk API. It does the same thing. + addSymbolsInBulk(Symbol.data()); +} + +void DbiModuleDescriptorBuilder::addSymbolsInBulk( + ArrayRef<uint8_t> BulkSymbols) { + // Do nothing for empty runs of symbols. + if (BulkSymbols.empty()) + return; + + Symbols.push_back(BulkSymbols); + // Symbols written to a PDB file are required to be 4 byte aligned. The same // is not true of object files. - assert(Symbol.length() % alignOf(CodeViewContainer::Pdb) == 0 && + assert(BulkSymbols.size() % alignOf(CodeViewContainer::Pdb) == 0 && "Invalid Symbol alignment!"); - SymbolByteSize += Symbol.length(); + SymbolByteSize += BulkSymbols.size(); } void DbiModuleDescriptorBuilder::addSourceFile(StringRef Path) { @@ -145,16 +154,11 @@ Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter, if (auto EC = SymbolWriter.writeInteger<uint32_t>(COFF::DEBUG_SECTION_MAGIC)) return EC; - BinaryItemStream<CVSymbol> Records(llvm::support::endianness::little); - Records.setItems(Symbols); - BinaryStreamRef RecordsRef(Records); - if (auto EC = SymbolWriter.writeStreamRef(RecordsRef)) - return EC; - if (auto EC = SymbolWriter.padToAlignment(4)) - return EC; - // TODO: Write C11 Line data + for (ArrayRef<uint8_t> Syms : Symbols) + SymbolWriter.writeBytes(Syms); assert(SymbolWriter.getOffset() % alignOf(CodeViewContainer::Pdb) == 0 && "Invalid debug section alignment!"); + // TODO: Write C11 Line data for (const auto &Builder : C13Builders) { assert(Builder && "Empty C13 Fragment Builder!"); if (auto EC = Builder->commit(SymbolWriter)) |