summaryrefslogtreecommitdiff
path: root/llvm/lib/ProfileData/SampleProfWriter.cpp
diff options
context:
space:
mode:
authorWilliam Junda Huang <williamjhuang@google.com>2023-10-17 17:09:39 -0400
committerGitHub <noreply@github.com>2023-10-17 21:09:39 +0000
commitef0e0adccd94ffdb10546491ef2719669754d3c9 (patch)
tree528c7b7065f03477c6bd5a3219104d724b137da7 /llvm/lib/ProfileData/SampleProfWriter.cpp
parente90ec58b132a7244bdd8d45dd482fd78fe487f37 (diff)
[llvm-profdata] Do not create numerical strings for MD5 function names read from a Sample Profile. (#66164)
This is phase 2 of the MD5 refactoring on Sample Profile following https://reviews.llvm.org/D147740 In previous implementation, when a MD5 Sample Profile is read, the reader first converts the MD5 values to strings, and then create a StringRef as if the numerical strings are regular function names, and later on IPO transformation passes perform string comparison over these numerical strings for profile matching. This is inefficient since it causes many small heap allocations. In this patch I created a class `ProfileFuncRef` that is similar to `StringRef` but it can represent a hash value directly without any conversion, and it will be more efficient (I will attach some benchmark results later) when being used in associative containers. ProfileFuncRef guarantees the same function name in string form or in MD5 form has the same hash value, which also fix a few issue in IPO passes where function matching/lookup only check for function name string, while returns a no-match if the profile is MD5. When testing on an internal large profile (> 1 GB, with more than 10 million functions), the full profile load time is reduced from 28 sec to 25 sec in average, and reading function offset table from 0.78s to 0.7s
Diffstat (limited to 'llvm/lib/ProfileData/SampleProfWriter.cpp')
-rw-r--r--llvm/lib/ProfileData/SampleProfWriter.cpp45
1 files changed, 24 insertions, 21 deletions
diff --git a/llvm/lib/ProfileData/SampleProfWriter.cpp b/llvm/lib/ProfileData/SampleProfWriter.cpp
index c11cd4dfa6a5..625e523f13ce 100644
--- a/llvm/lib/ProfileData/SampleProfWriter.cpp
+++ b/llvm/lib/ProfileData/SampleProfWriter.cpp
@@ -240,7 +240,7 @@ std::error_code SampleProfileWriterExtBinaryBase::writeContextIdx(
if (Context.hasContext())
return writeCSNameIdx(Context);
else
- return SampleProfileWriterBinary::writeNameIdx(Context.getName());
+ return SampleProfileWriterBinary::writeNameIdx(Context.getFunction());
}
std::error_code
@@ -346,7 +346,7 @@ std::error_code SampleProfileWriterExtBinaryBase::writeNameTable() {
return SampleProfileWriterBinary::writeNameTable();
auto &OS = *OutputStream;
- std::set<StringRef> V;
+ std::set<FunctionId> V;
stablizeNameTable(NameTable, V);
// Write out the MD5 name table. We wrote unencoded MD5 so reader can
@@ -355,7 +355,7 @@ std::error_code SampleProfileWriterExtBinaryBase::writeNameTable() {
encodeULEB128(NameTable.size(), OS);
support::endian::Writer Writer(OS, llvm::endianness::little);
for (auto N : V)
- Writer.write(hashFuncName(N));
+ Writer.write(N.getHashCode());
return sampleprof_error::success;
}
@@ -369,10 +369,13 @@ std::error_code SampleProfileWriterExtBinaryBase::writeNameTableSection(
// If NameTable contains ".__uniq." suffix, set SecFlagUniqSuffix flag
// so compiler won't strip the suffix during profile matching after
// seeing the flag in the profile.
- for (const auto &I : NameTable) {
- if (I.first.contains(FunctionSamples::UniqSuffix)) {
- addSectionFlag(SecNameTable, SecNameTableFlags::SecFlagUniqSuffix);
- break;
+ // Original names are unavailable if using MD5, so this option has no use.
+ if (!UseMD5) {
+ for (const auto &I : NameTable) {
+ if (I.first.stringRef().contains(FunctionSamples::UniqSuffix)) {
+ addSectionFlag(SecNameTable, SecNameTableFlags::SecFlagUniqSuffix);
+ break;
+ }
}
}
@@ -399,7 +402,7 @@ std::error_code SampleProfileWriterExtBinaryBase::writeCSNameTableSection() {
auto Frames = Context.getContextFrames();
encodeULEB128(Frames.size(), OS);
for (auto &Callsite : Frames) {
- if (std::error_code EC = writeNameIdx(Callsite.FuncName))
+ if (std::error_code EC = writeNameIdx(Callsite.Func))
return EC;
encodeULEB128(Callsite.Location.LineOffset, OS);
encodeULEB128(Callsite.Location.Discriminator, OS);
@@ -567,7 +570,7 @@ std::error_code SampleProfileWriterText::writeSample(const FunctionSamples &S) {
if (FunctionSamples::ProfileIsCS)
OS << "[" << S.getContext().toString() << "]:" << S.getTotalSamples();
else
- OS << S.getName() << ":" << S.getTotalSamples();
+ OS << S.getFunction() << ":" << S.getTotalSamples();
if (Indent == 0)
OS << ":" << S.getHeadSamples();
@@ -627,10 +630,10 @@ std::error_code SampleProfileWriterText::writeSample(const FunctionSamples &S) {
std::error_code
SampleProfileWriterBinary::writeContextIdx(const SampleContext &Context) {
assert(!Context.hasContext() && "cs profile is not supported");
- return writeNameIdx(Context.getName());
+ return writeNameIdx(Context.getFunction());
}
-std::error_code SampleProfileWriterBinary::writeNameIdx(StringRef FName) {
+std::error_code SampleProfileWriterBinary::writeNameIdx(FunctionId FName) {
auto &NTable = getNameTable();
const auto &Ret = NTable.find(FName);
if (Ret == NTable.end())
@@ -639,13 +642,13 @@ std::error_code SampleProfileWriterBinary::writeNameIdx(StringRef FName) {
return sampleprof_error::success;
}
-void SampleProfileWriterBinary::addName(StringRef FName) {
+void SampleProfileWriterBinary::addName(FunctionId FName) {
auto &NTable = getNameTable();
NTable.insert(std::make_pair(FName, 0));
}
void SampleProfileWriterBinary::addContext(const SampleContext &Context) {
- addName(Context.getName());
+ addName(Context.getFunction());
}
void SampleProfileWriterBinary::addNames(const FunctionSamples &S) {
@@ -653,14 +656,14 @@ void SampleProfileWriterBinary::addNames(const FunctionSamples &S) {
for (const auto &I : S.getBodySamples()) {
const SampleRecord &Sample = I.second;
for (const auto &J : Sample.getCallTargets())
- addName(J.first());
+ addName(J.first);
}
// Recursively add all the names for inlined callsites.
for (const auto &J : S.getCallsiteSamples())
for (const auto &FS : J.second) {
const FunctionSamples &CalleeSamples = FS.second;
- addName(CalleeSamples.getName());
+ addName(CalleeSamples.getFunction());
addNames(CalleeSamples);
}
}
@@ -669,26 +672,26 @@ void SampleProfileWriterExtBinaryBase::addContext(
const SampleContext &Context) {
if (Context.hasContext()) {
for (auto &Callsite : Context.getContextFrames())
- SampleProfileWriterBinary::addName(Callsite.FuncName);
+ SampleProfileWriterBinary::addName(Callsite.Func);
CSNameTable.insert(std::make_pair(Context, 0));
} else {
- SampleProfileWriterBinary::addName(Context.getName());
+ SampleProfileWriterBinary::addName(Context.getFunction());
}
}
void SampleProfileWriterBinary::stablizeNameTable(
- MapVector<StringRef, uint32_t> &NameTable, std::set<StringRef> &V) {
+ MapVector<FunctionId, uint32_t> &NameTable, std::set<FunctionId> &V) {
// Sort the names to make NameTable deterministic.
for (const auto &I : NameTable)
V.insert(I.first);
int i = 0;
- for (const StringRef &N : V)
+ for (const FunctionId &N : V)
NameTable[N] = i++;
}
std::error_code SampleProfileWriterBinary::writeNameTable() {
auto &OS = *OutputStream;
- std::set<StringRef> V;
+ std::set<FunctionId> V;
stablizeNameTable(NameTable, V);
// Write out the name table.
@@ -835,7 +838,7 @@ std::error_code SampleProfileWriterBinary::writeBody(const FunctionSamples &S) {
encodeULEB128(Sample.getSamples(), OS);
encodeULEB128(Sample.getCallTargets().size(), OS);
for (const auto &J : Sample.getSortedCallTargets()) {
- StringRef Callee = J.first;
+ FunctionId Callee = J.first;
uint64_t CalleeSamples = J.second;
if (std::error_code EC = writeNameIdx(Callee))
return EC;