diff options
author | Choongwoo Han <choongwoo.han@microsoft.com> | 2021-03-23 15:59:45 -0700 |
---|---|---|
committer | Vedant Kumar <vsk@apple.com> | 2021-03-23 16:25:20 -0700 |
commit | 772e1dd1ddc0cf138ab1a5e88d9614229e978491 (patch) | |
tree | d363d0998570eac332aa006f176d3c71e089de7e /llvm/lib/ProfileData/Coverage/CoverageMapping.cpp | |
parent | 48d9b2fd8ea36f87b3fc57ddb101ed99d20f25bf (diff) | |
download | llvm-772e1dd1ddc0cf138ab1a5e88d9614229e978491.zip llvm-772e1dd1ddc0cf138ab1a5e88d9614229e978491.tar.gz llvm-772e1dd1ddc0cf138ab1a5e88d9614229e978491.tar.bz2 |
[Coverage] Load records immediately
The current implementation keeps buffers generated for each object file
until it completes loading of all files. This approach requires a lot of memory
if there are a lot of huge object files. Thus, make it to load coverage records
immediately rather than waiting for other binaries to be loaded.
This reduces memory usage of llvm-cov from >128GB to 5GB when
loading Chromium binaries in Windows.
Additional testing: check-profile, check-llvm
Differential Revision: https://reviews.llvm.org/D99110
Diffstat (limited to 'llvm/lib/ProfileData/Coverage/CoverageMapping.cpp')
-rw-r--r-- | llvm/lib/ProfileData/Coverage/CoverageMapping.cpp | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp index cdbcde5..1958e31 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -281,21 +281,29 @@ Error CoverageMapping::loadFunctionRecord( return Error::success(); } -Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load( +// This function is for memory optimization by shortening the lifetimes +// of CoverageMappingReader instances. +Error CoverageMapping::loadFromReaders( ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders, - IndexedInstrProfReader &ProfileReader) { - auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping()); - + IndexedInstrProfReader &ProfileReader, CoverageMapping &Coverage) { for (const auto &CoverageReader : CoverageReaders) { for (auto RecordOrErr : *CoverageReader) { if (Error E = RecordOrErr.takeError()) - return std::move(E); + return E; const auto &Record = *RecordOrErr; - if (Error E = Coverage->loadFunctionRecord(Record, ProfileReader)) - return std::move(E); + if (Error E = Coverage.loadFunctionRecord(Record, ProfileReader)) + return E; } } + return Error::success(); +} +Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load( + ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders, + IndexedInstrProfReader &ProfileReader) { + auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping()); + if (Error E = loadFromReaders(CoverageReaders, ProfileReader, *Coverage)) + return std::move(E); return std::move(Coverage); } @@ -316,16 +324,18 @@ CoverageMapping::load(ArrayRef<StringRef> ObjectFilenames, if (Error E = ProfileReaderOrErr.takeError()) return std::move(E); auto ProfileReader = std::move(ProfileReaderOrErr.get()); + auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping()); + bool DataFound = false; - SmallVector<std::unique_ptr<CoverageMappingReader>, 4> Readers; - SmallVector<std::unique_ptr<MemoryBuffer>, 4> Buffers; for (const auto &File : llvm::enumerate(ObjectFilenames)) { - auto CovMappingBufOrErr = MemoryBuffer::getFileOrSTDIN(File.value()); + auto CovMappingBufOrErr = MemoryBuffer::getFileOrSTDIN( + File.value(), /*FileSize=*/-1, /*RequiresNullTerminator=*/false); if (std::error_code EC = CovMappingBufOrErr.getError()) return errorCodeToError(EC); StringRef Arch = Arches.empty() ? StringRef() : Arches[File.index()]; MemoryBufferRef CovMappingBufRef = CovMappingBufOrErr.get()->getMemBufferRef(); + SmallVector<std::unique_ptr<MemoryBuffer>, 4> Buffers; auto CoverageReadersOrErr = BinaryCoverageReader::create(CovMappingBufRef, Arch, Buffers); if (Error E = CoverageReadersOrErr.takeError()) { @@ -335,15 +345,19 @@ CoverageMapping::load(ArrayRef<StringRef> ObjectFilenames, // E == success (originally a no_data_found error). continue; } + + SmallVector<std::unique_ptr<CoverageMappingReader>, 4> Readers; for (auto &Reader : CoverageReadersOrErr.get()) Readers.push_back(std::move(Reader)); - Buffers.push_back(std::move(CovMappingBufOrErr.get())); + DataFound |= !Readers.empty(); + if (Error E = loadFromReaders(Readers, *ProfileReader, *Coverage)) + return std::move(E); } // If no readers were created, either no objects were provided or none of them // had coverage data. Return an error in the latter case. - if (Readers.empty() && !ObjectFilenames.empty()) + if (!DataFound && !ObjectFilenames.empty()) return make_error<CoverageMapError>(coveragemap_error::no_data_found); - return load(Readers, *ProfileReader); + return std::move(Coverage); } namespace { |