Prototype: Reduce llvm-profdata merge memory usage further
The InstrProfWriter already stores the name and hash of the record in
the nested maps it uses for lookup while merging - this data is
duplicated in the value within the maps.
Refactor the InstrProfRecord to use a nested struct for the counters
themselves so that InstrProfWriter can use this nested struct alone
without the name or hash duplicated there.
This work is incomplete, but enough to demonstrate the value (around a
50% decrease in memory usage for a large test case (10GB -> 5GB)).
Though most of that decrease is probably from removing the
SoftInstrProfError as well, but I haven't implemented a replacement for
it yet. (it needs to go with the counters, because the operations on the
counters - merging, etc, are where the failures are - unlike the
name/hash which are totally unused by those counter-related operations
and thus easy to split out)
Ongoing discussion about removing SoftInstrProfError as a field of the
InstrProfRecord is happening on the thread that added it - including
the possibility of moving back towards an earlier version of that
proposed patch that passed SoftInstrProfError through the various APIs,
rather than as a member of InstrProfRecord.
Reviewers: davidxl
Differential Revision: https://reviews.llvm.org/D34838
llvm-svn: 307298
diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp
index 1ed1fb8..1b39a06 100644
--- a/llvm/lib/ProfileData/InstrProfReader.cpp
+++ b/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -221,7 +221,7 @@
#undef VP_READ_ADVANCE
}
-Error TextInstrProfReader::readNextRecord(InstrProfRecord &Record) {
+Error TextInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) {
// Skip empty lines and comments.
while (!Line.is_at_end() && (Line->empty() || Line->startswith("#")))
++Line;
@@ -377,13 +377,13 @@
}
template <class IntPtrT>
-Error RawInstrProfReader<IntPtrT>::readName(InstrProfRecord &Record) {
+Error RawInstrProfReader<IntPtrT>::readName(NamedInstrProfRecord &Record) {
Record.Name = getName(Data->NameRef);
return success();
}
template <class IntPtrT>
-Error RawInstrProfReader<IntPtrT>::readFuncHash(InstrProfRecord &Record) {
+Error RawInstrProfReader<IntPtrT>::readFuncHash(NamedInstrProfRecord &Record) {
Record.Hash = swap(Data->FuncHash);
return success();
}
@@ -445,7 +445,7 @@
}
template <class IntPtrT>
-Error RawInstrProfReader<IntPtrT>::readNextRecord(InstrProfRecord &Record) {
+Error RawInstrProfReader<IntPtrT>::readNextRecord(NamedInstrProfRecord &Record) {
if (atEnd())
// At this point, ValueDataStart field points to the next header.
if (Error E = readNextHeader(getNextHeaderPos()))
@@ -550,7 +550,7 @@
template <typename HashTableImpl>
Error InstrProfReaderIndex<HashTableImpl>::getRecords(
- StringRef FuncName, ArrayRef<InstrProfRecord> &Data) {
+ StringRef FuncName, ArrayRef<NamedInstrProfRecord> &Data) {
auto Iter = HashTable->find(FuncName);
if (Iter == HashTable->end())
return make_error<InstrProfError>(instrprof_error::unknown_function);
@@ -564,7 +564,7 @@
template <typename HashTableImpl>
Error InstrProfReaderIndex<HashTableImpl>::getRecords(
- ArrayRef<InstrProfRecord> &Data) {
+ ArrayRef<NamedInstrProfRecord> &Data) {
if (atEnd())
return make_error<InstrProfError>(instrprof_error::eof);
@@ -644,7 +644,7 @@
InstrProfSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs);
// FIXME: This only computes an empty summary. Need to call addRecord for
- // all InstrProfRecords to get the correct summary.
+ // all NamedInstrProfRecords to get the correct summary.
this->Summary = Builder.getSummary();
return Cur;
}
@@ -707,7 +707,7 @@
Expected<InstrProfRecord>
IndexedInstrProfReader::getInstrProfRecord(StringRef FuncName,
uint64_t FuncHash) {
- ArrayRef<InstrProfRecord> Data;
+ ArrayRef<NamedInstrProfRecord> Data;
Error Err = Index->getRecords(FuncName, Data);
if (Err)
return std::move(Err);
@@ -732,10 +732,10 @@
return success();
}
-Error IndexedInstrProfReader::readNextRecord(InstrProfRecord &Record) {
+Error IndexedInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) {
static unsigned RecordIndex = 0;
- ArrayRef<InstrProfRecord> Data;
+ ArrayRef<NamedInstrProfRecord> Data;
Error E = Index->getRecords(Data);
if (E)
diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp
index 9efea78..a1961b6 100644
--- a/llvm/lib/ProfileData/InstrProfWriter.cpp
+++ b/llvm/lib/ProfileData/InstrProfWriter.cpp
@@ -176,20 +176,25 @@
this->Sparse = Sparse;
}
-Error InstrProfWriter::addRecord(InstrProfRecord &&I, uint64_t Weight) {
- auto &ProfileDataMap = FunctionData[I.Name];
+Error InstrProfWriter::addRecord(NamedInstrProfRecord &&I, uint64_t Weight) {
+ auto Name = I.Name;
+ auto Hash = I.Hash;
+ return addRecord(Name, Hash, std::move(I), Weight);
+}
+
+Error InstrProfWriter::addRecord(StringRef Name, uint64_t Hash,
+ InstrProfRecord &&I, uint64_t Weight) {
+ auto &ProfileDataMap = FunctionData[Name];
bool NewFunc;
ProfilingData::iterator Where;
std::tie(Where, NewFunc) =
- ProfileDataMap.insert(std::make_pair(I.Hash, InstrProfRecord()));
+ ProfileDataMap.insert(std::make_pair(Hash, InstrProfRecord()));
InstrProfRecord &Dest = Where->second;
if (NewFunc) {
// We've never seen a function with this name and hash, add it.
Dest = std::move(I);
- // Fix up the name to avoid dangling reference.
- Dest.Name = FunctionData.find(Dest.Name)->getKey();
if (Weight > 1)
Dest.scale(Weight);
} else {
@@ -205,7 +210,7 @@
Error InstrProfWriter::mergeRecordsFromWriter(InstrProfWriter &&IPW) {
for (auto &I : IPW.FunctionData)
for (auto &Func : I.getValue())
- if (Error E = addRecord(std::move(Func.second), 1))
+ if (Error E = addRecord(I.getKey(), Func.first, std::move(Func.second)))
return E;
return Error::success();
}
@@ -323,11 +328,12 @@
#include "llvm/ProfileData/InstrProfData.inc"
};
-void InstrProfWriter::writeRecordInText(const InstrProfRecord &Func,
+void InstrProfWriter::writeRecordInText(StringRef Name, uint64_t Hash,
+ const InstrProfRecord &Func,
InstrProfSymtab &Symtab,
raw_fd_ostream &OS) {
- OS << Func.Name << "\n";
- OS << "# Func Hash:\n" << Func.Hash << "\n";
+ OS << Name << "\n";
+ OS << "# Func Hash:\n" << Hash << "\n";
OS << "# Num Counters:\n" << Func.Counts.size() << "\n";
OS << "# Counter Values:\n";
for (uint64_t Count : Func.Counts)
@@ -375,6 +381,6 @@
for (const auto &I : FunctionData)
if (shouldEncodeData(I.getValue()))
for (const auto &Func : I.getValue())
- writeRecordInText(Func.second, Symtab, OS);
+ writeRecordInText(I.getKey(), Func.first, Func.second, Symtab, OS);
return Error::success();
}