diff options
Diffstat (limited to 'llvm/lib/ProfileData/SampleProfReader.cpp')
-rw-r--r-- | llvm/lib/ProfileData/SampleProfReader.cpp | 121 |
1 files changed, 88 insertions, 33 deletions
diff --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp index fbdd9a3..d71fe11 100644 --- a/llvm/lib/ProfileData/SampleProfReader.cpp +++ b/llvm/lib/ProfileData/SampleProfReader.cpp @@ -61,9 +61,9 @@ static cl::opt<bool> ProfileIsFSDisciminator( /// /// \param FContext Name + context of the function to print. /// \param OS Stream to emit the output to. -void SampleProfileReader::dumpFunctionProfile(SampleContext FContext, +void SampleProfileReader::dumpFunctionProfile(const FunctionSamples &FS, raw_ostream &OS) { - OS << "Function: " << FContext.toString() << ": " << Profiles[FContext]; + OS << "Function: " << FS.getContext().toString() << ": " << FS; } /// Dump all the function profiles found on stream \p OS. @@ -71,7 +71,7 @@ void SampleProfileReader::dump(raw_ostream &OS) { std::vector<NameFunctionSamples> V; sortFuncProfiles(Profiles, V); for (const auto &I : V) - dumpFunctionProfile(I.first, OS); + dumpFunctionProfile(*I.second, OS); } static void dumpFunctionProfileJson(const FunctionSamples &S, @@ -355,9 +355,7 @@ std::error_code SampleProfileReaderText::readImpl() { SampleContext FContext(FName, CSNameTable); if (FContext.hasContext()) ++CSProfileCount; - Profiles[FContext] = FunctionSamples(); - FunctionSamples &FProfile = Profiles[FContext]; - FProfile.setContext(FContext); + FunctionSamples &FProfile = Profiles.Create(FContext); MergeResult(Result, FProfile.addTotalSamples(NumSamples)); MergeResult(Result, FProfile.addHeadSamples(NumHeadSamples)); InlineStack.clear(); @@ -525,7 +523,8 @@ inline ErrorOr<size_t> SampleProfileReaderBinary::readStringIndex(T &Table) { return *Idx; } -ErrorOr<StringRef> SampleProfileReaderBinary::readStringFromTable() { +ErrorOr<StringRef> +SampleProfileReaderBinary::readStringFromTable(size_t *RetIdx) { auto Idx = readStringIndex(NameTable); if (std::error_code EC = Idx.getError()) return EC; @@ -543,30 +542,48 @@ ErrorOr<StringRef> SampleProfileReaderBinary::readStringFromTable() { MD5NameMemStart + (*Idx) * sizeof(uint64_t)); SR = MD5StringBuf.emplace_back(std::to_string(FID)); } + if (RetIdx) + *RetIdx = *Idx; return SR; } -ErrorOr<SampleContextFrames> SampleProfileReaderBinary::readContextFromTable() { +ErrorOr<SampleContextFrames> +SampleProfileReaderBinary::readContextFromTable(size_t *RetIdx) { auto ContextIdx = readNumber<size_t>(); if (std::error_code EC = ContextIdx.getError()) return EC; if (*ContextIdx >= CSNameTable.size()) return sampleprof_error::truncated_name_table; + if (RetIdx) + *RetIdx = *ContextIdx; return CSNameTable[*ContextIdx]; } -ErrorOr<SampleContext> SampleProfileReaderBinary::readSampleContextFromTable() { +ErrorOr<std::pair<SampleContext, hash_code>> +SampleProfileReaderBinary::readSampleContextFromTable() { + SampleContext Context; + size_t Idx; if (ProfileIsCS) { - auto FContext(readContextFromTable()); + auto FContext(readContextFromTable(&Idx)); if (std::error_code EC = FContext.getError()) return EC; - return SampleContext(*FContext); + Context = SampleContext(*FContext); } else { - auto FName(readStringFromTable()); + auto FName(readStringFromTable(&Idx)); if (std::error_code EC = FName.getError()) return EC; - return SampleContext(*FName); + Context = SampleContext(*FName); + } + hash_code Hash = MD5SampleContextStart[Idx]; + // Lazy computing of hash value, write back to the table to cache it. Only + // compute the context's hash value if it is being referenced for the first + // time. + if (Hash == hash_code(0)) { + assert(MD5SampleContextStart == MD5SampleContextTable.data()); + Hash = Context.getHashCode(); + MD5SampleContextTable[Idx] = Hash; } + return std::make_pair(Context, Hash); } std::error_code @@ -659,16 +676,18 @@ SampleProfileReaderBinary::readFuncProfile(const uint8_t *Start) { if (std::error_code EC = NumHeadSamples.getError()) return EC; - ErrorOr<SampleContext> FContext(readSampleContextFromTable()); - if (std::error_code EC = FContext.getError()) + auto FContextHash(readSampleContextFromTable()); + if (std::error_code EC = FContextHash.getError()) return EC; - Profiles[*FContext] = FunctionSamples(); - FunctionSamples &FProfile = Profiles[*FContext]; - FProfile.setContext(*FContext); + auto &[FContext, Hash] = *FContextHash; + // Use the cached hash value for insertion instead of recalculating it. + auto Res = Profiles.try_emplace(Hash, FContext, FunctionSamples()); + FunctionSamples &FProfile = Res.first->second; + FProfile.setContext(FContext); FProfile.addHeadSamples(*NumHeadSamples); - if (FContext->hasContext()) + if (FContext.hasContext()) CSProfileCount++; if (std::error_code EC = readProfile(FProfile)) @@ -816,18 +835,21 @@ std::error_code SampleProfileReaderExtBinaryBase::readFuncOffsetTable() { FuncOffsetTable.reserve(*Size); for (uint64_t I = 0; I < *Size; ++I) { - auto FContext(readSampleContextFromTable()); - if (std::error_code EC = FContext.getError()) + auto FContextHash(readSampleContextFromTable()); + if (std::error_code EC = FContextHash.getError()) return EC; + auto &[FContext, Hash] = *FContextHash; auto Offset = readNumber<uint64_t>(); if (std::error_code EC = Offset.getError()) return EC; if (UseFuncOffsetList) - FuncOffsetList.emplace_back(*FContext, *Offset); + FuncOffsetList.emplace_back(FContext, *Offset); else - FuncOffsetTable[*FContext] = *Offset; + // Because Porfiles replace existing value with new value if collision + // happens, we also use the latest offset so that they are consistent. + FuncOffsetTable[Hash] = *Offset; } return sampleprof_error::success; @@ -900,8 +922,8 @@ std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles() { } else if (useMD5()) { assert(!useFuncOffsetList()); for (auto Name : FuncsToUse) { - auto GUID = std::to_string(MD5Hash(Name)); - auto iter = FuncOffsetTable.find(StringRef(GUID)); + auto GUID = MD5Hash(Name); + auto iter = FuncOffsetTable.find(GUID); if (iter == FuncOffsetTable.end()) continue; const uint8_t *FuncProfileAddr = Start + iter->second; @@ -922,7 +944,7 @@ std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles() { } else { assert(!useFuncOffsetList()); for (auto Name : FuncsToUse) { - auto iter = FuncOffsetTable.find(Name); + auto iter = FuncOffsetTable.find(MD5Hash(Name)); if (iter == FuncOffsetTable.end()) continue; const uint8_t *FuncProfileAddr = Start + iter->second; @@ -1050,17 +1072,30 @@ std::error_code SampleProfileReaderBinary::readNameTable() { NameTable.clear(); NameTable.reserve(*Size); + if (!ProfileIsCS) { + MD5SampleContextTable.clear(); + if (UseMD5) + MD5SampleContextTable.reserve(*Size); + else + // If we are using strings, delay MD5 computation since only a portion of + // names are used by top level functions. Use 0 to indicate MD5 value is + // to be calculated as no known string has a MD5 value of 0. + MD5SampleContextTable.resize(*Size); + } for (size_t I = 0; I < *Size; ++I) { auto Name(readString()); if (std::error_code EC = Name.getError()) return EC; if (UseMD5) { uint64_t FID = MD5Hash(*Name); + if (!ProfileIsCS) + MD5SampleContextTable.emplace_back(FID); NameTable.emplace_back(MD5StringBuf.emplace_back(std::to_string(FID))); } else NameTable.push_back(*Name); } - + if (!ProfileIsCS) + MD5SampleContextStart = MD5SampleContextTable.data(); return sampleprof_error::success; } @@ -1088,6 +1123,8 @@ SampleProfileReaderExtBinaryBase::readNameTableSec(bool IsMD5, NameTable.clear(); NameTable.resize(*Size); MD5NameMemStart = Data; + if (!ProfileIsCS) + MD5SampleContextStart = reinterpret_cast<const hash_code *>(Data); Data = Data + (*Size) * sizeof(uint64_t); return sampleprof_error::success; } @@ -1101,12 +1138,20 @@ SampleProfileReaderExtBinaryBase::readNameTableSec(bool IsMD5, MD5StringBuf.reserve(MD5StringBuf.size() + *Size); NameTable.clear(); NameTable.reserve(*Size); + if (!ProfileIsCS) { + MD5SampleContextTable.clear(); + MD5SampleContextTable.reserve(*Size); + } for (size_t I = 0; I < *Size; ++I) { auto FID = readNumber<uint64_t>(); if (std::error_code EC = FID.getError()) return EC; + if (!ProfileIsCS) + MD5SampleContextTable.emplace_back(*FID); NameTable.emplace_back(MD5StringBuf.emplace_back(std::to_string(*FID))); } + if (!ProfileIsCS) + MD5SampleContextStart = MD5SampleContextTable.data(); return sampleprof_error::success; } @@ -1124,6 +1169,14 @@ std::error_code SampleProfileReaderExtBinaryBase::readCSNameTableSec() { CSNameTable.clear(); CSNameTable.reserve(*Size); + if (ProfileIsCS) { + // Delay MD5 computation of CS context until they are needed. Use 0 to + // indicate MD5 value is to be calculated as no known string has a MD5 + // value of 0. + MD5SampleContextTable.clear(); + MD5SampleContextTable.resize(*Size); + MD5SampleContextStart = MD5SampleContextTable.data(); + } for (size_t I = 0; I < *Size; ++I) { CSNameTable.emplace_back(SampleContextFrameVector()); auto ContextSize = readNumber<uint32_t>(); @@ -1187,16 +1240,17 @@ SampleProfileReaderExtBinaryBase::readFuncMetadata(bool ProfileHasAttribute, if (std::error_code EC = Discriminator.getError()) return EC; - auto FContext(readSampleContextFromTable()); - if (std::error_code EC = FContext.getError()) + auto FContextHash(readSampleContextFromTable()); + if (std::error_code EC = FContextHash.getError()) return EC; + auto &[FContext, Hash] = *FContextHash; FunctionSamples *CalleeProfile = nullptr; if (FProfile) { CalleeProfile = const_cast<FunctionSamples *>( &FProfile->functionSamplesAt(LineLocation( *LineOffset, - *Discriminator))[std::string(FContext.get().getName())]); + *Discriminator))[std::string(FContext.getName())]); } if (std::error_code EC = readFuncMetadata(ProfileHasAttribute, CalleeProfile)) @@ -1211,11 +1265,12 @@ SampleProfileReaderExtBinaryBase::readFuncMetadata(bool ProfileHasAttribute, std::error_code SampleProfileReaderExtBinaryBase::readFuncMetadata(bool ProfileHasAttribute) { while (Data < End) { - auto FContext(readSampleContextFromTable()); - if (std::error_code EC = FContext.getError()) + auto FContextHash(readSampleContextFromTable()); + if (std::error_code EC = FContextHash.getError()) return EC; + auto &[FContext, Hash] = *FContextHash; FunctionSamples *FProfile = nullptr; - auto It = Profiles.find(*FContext); + auto It = Profiles.find(FContext); if (It != Profiles.end()) FProfile = &It->second; |