Skip to content

Commit 5add295

Browse files
[memprof] Use IndexedMemProfRecord in MemProfReader (NFC) (#117613)
IndexedMemProfRecord contains a complete package of the MemProf profile, including frames, call stacks, and records. This patch replaces the three member variables of MemProfReader with IndexedMemProfRecord. This transition significantly simplies both the constructor and the final "take" method: MemProfReader(IndexedMemProfData MemProfData) : MemProfData(std::move(MemProfData)) {} IndexedMemProfData takeMemProfData() { return std::move(MemProfData); }
1 parent 8ffe63f commit 5add295

File tree

3 files changed

+23
-47
lines changed

3 files changed

+23
-47
lines changed

llvm/include/llvm/ProfileData/MemProfReader.h

Lines changed: 15 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -42,43 +42,29 @@ class MemProfReader {
4242
using Iterator = InstrProfIterator<GuidMemProfRecordPair, MemProfReader>;
4343
Iterator end() { return Iterator(); }
4444
Iterator begin() {
45-
Iter = FunctionProfileData.begin();
45+
Iter = MemProfData.Records.begin();
4646
return Iterator(this);
4747
}
4848

49-
// Take the complete profile data.
50-
IndexedMemProfData takeMemProfData() {
51-
// TODO: Once we replace the three member variables, namely IdToFrame,
52-
// CSIdToCallStack, and FunctionProfileData, with MemProfData, replace the
53-
// following code with just "return std::move(MemProfData);".
54-
IndexedMemProfData MemProfData;
55-
// Copy key-value pairs because IdToFrame uses DenseMap, whereas
56-
// IndexedMemProfData::Frames uses MapVector.
57-
for (const auto &[FrameId, F] : IdToFrame)
58-
MemProfData.Frames.try_emplace(FrameId, F);
59-
// Copy key-value pairs because CSIdToCallStack uses DenseMap, whereas
60-
// IndexedMemProfData::CallStacks uses MapVector.
61-
for (const auto &[CSId, CS] : CSIdToCallStack)
62-
MemProfData.CallStacks.try_emplace(CSId, CS);
63-
MemProfData.Records = FunctionProfileData;
64-
return MemProfData;
65-
}
49+
// Take the complete profile data. Once this function is invoked,
50+
// MemProfReader no longer owns the MemProf profile.
51+
IndexedMemProfData takeMemProfData() { return std::move(MemProfData); }
6652

6753
virtual Error
6854
readNextRecord(GuidMemProfRecordPair &GuidRecord,
6955
std::function<const Frame(const FrameId)> Callback = nullptr) {
70-
if (FunctionProfileData.empty())
56+
if (MemProfData.Records.empty())
7157
return make_error<InstrProfError>(instrprof_error::empty_raw_profile);
7258

73-
if (Iter == FunctionProfileData.end())
59+
if (Iter == MemProfData.Records.end())
7460
return make_error<InstrProfError>(instrprof_error::eof);
7561

7662
if (Callback == nullptr)
7763
Callback =
7864
std::bind(&MemProfReader::idToFrame, this, std::placeholders::_1);
7965

80-
CallStackIdConverter<decltype(CSIdToCallStack)> CSIdConv(CSIdToCallStack,
81-
Callback);
66+
CallStackIdConverter<decltype(MemProfData.CallStacks)> CSIdConv(
67+
MemProfData.CallStacks, Callback);
8268

8369
const IndexedMemProfRecord &IndexedRecord = Iter->second;
8470
GuidRecord = {
@@ -97,28 +83,18 @@ class MemProfReader {
9783
virtual ~MemProfReader() = default;
9884

9985
// Initialize the MemProfReader with the given MemProf profile.
100-
MemProfReader(IndexedMemProfData MemProfData) {
101-
for (const auto &[FrameId, F] : MemProfData.Frames)
102-
IdToFrame.try_emplace(FrameId, F);
103-
for (const auto &[CSId, CS] : MemProfData.CallStacks)
104-
CSIdToCallStack.try_emplace(CSId, CS);
105-
FunctionProfileData = std::move(MemProfData.Records);
106-
}
86+
MemProfReader(IndexedMemProfData &&MemProfData)
87+
: MemProfData(std::move(MemProfData)) {}
10788

10889
protected:
10990
// A helper method to extract the frame from the IdToFrame map.
11091
const Frame &idToFrame(const FrameId Id) const {
111-
auto It = IdToFrame.find(Id);
112-
assert(It != IdToFrame.end() && "Id not found in map.");
113-
return It->getSecond();
92+
auto It = MemProfData.Frames.find(Id);
93+
assert(It != MemProfData.Frames.end() && "Id not found in map.");
94+
return It->second;
11495
}
115-
// A mapping from FrameId (a hash of the contents) to the frame.
116-
llvm::DenseMap<FrameId, Frame> IdToFrame;
117-
// A mapping from CallStackId to the call stack.
118-
llvm::DenseMap<CallStackId, llvm::SmallVector<FrameId>> CSIdToCallStack;
119-
// A mapping from function GUID, hash of the canonical function symbol to the
120-
// memprof profile data for that function, i.e allocation and callsite info.
121-
llvm::MapVector<GlobalValue::GUID, IndexedMemProfRecord> FunctionProfileData;
96+
// A complete pacakge of the MemProf profile.
97+
IndexedMemProfData MemProfData;
12298
// An iterator to the internal function profile data structure.
12399
llvm::MapVector<GlobalValue::GUID, IndexedMemProfRecord>::iterator Iter;
124100
};

llvm/lib/ProfileData/MemProfReader.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ bool RawMemProfReader::hasFormat(const MemoryBuffer &Buffer) {
304304

305305
void RawMemProfReader::printYAML(raw_ostream &OS) {
306306
uint64_t NumAllocFunctions = 0, NumMibInfo = 0;
307-
for (const auto &KV : FunctionProfileData) {
307+
for (const auto &KV : MemProfData.Records) {
308308
const size_t NumAllocSites = KV.second.AllocSites.size();
309309
if (NumAllocSites > 0) {
310310
NumAllocFunctions++;
@@ -500,13 +500,13 @@ Error RawMemProfReader::mapRawProfileToRecords() {
500500
}
501501

502502
CallStackId CSId = hashCallStack(Callstack);
503-
CSIdToCallStack.insert({CSId, Callstack});
503+
MemProfData.CallStacks.insert({CSId, Callstack});
504504

505505
// We attach the memprof record to each function bottom-up including the
506506
// first non-inline frame.
507507
for (size_t I = 0; /*Break out using the condition below*/; I++) {
508508
const Frame &F = idToFrame(Callstack[I]);
509-
IndexedMemProfRecord &Record = FunctionProfileData[F.Function];
509+
IndexedMemProfRecord &Record = MemProfData.Records[F.Function];
510510
Record.AllocSites.emplace_back(Callstack, CSId, MIB);
511511

512512
if (!F.IsInlineFrame)
@@ -518,10 +518,10 @@ Error RawMemProfReader::mapRawProfileToRecords() {
518518
for (const auto &[Id, Locs] : PerFunctionCallSites) {
519519
// Some functions may have only callsite data and no allocation data. Here
520520
// we insert a new entry for callsite data if we need to.
521-
IndexedMemProfRecord &Record = FunctionProfileData[Id];
521+
IndexedMemProfRecord &Record = MemProfData.Records[Id];
522522
for (LocationPtr Loc : Locs) {
523523
CallStackId CSId = hashCallStack(*Loc);
524-
CSIdToCallStack.insert({CSId, *Loc});
524+
MemProfData.CallStacks.insert({CSId, *Loc});
525525
Record.CallSites.push_back(*Loc);
526526
Record.CallSiteIds.push_back(CSId);
527527
}
@@ -585,7 +585,7 @@ Error RawMemProfReader::symbolizeAndFilterStackFrames(
585585
}
586586

587587
const FrameId Hash = F.hash();
588-
IdToFrame.insert({Hash, F});
588+
MemProfData.Frames.insert({Hash, F});
589589
SymbolizedFrame[VAddr].push_back(Hash);
590590
}
591591
}

llvm/unittests/ProfileData/MemProfTest.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ TEST(MemProf, BaseMemProfReader) {
440440
FakeRecord.AllocSites.emplace_back(/*CSId=*/CSId, /*MB=*/Block);
441441
MemProfData.Records.insert({F1.hash(), FakeRecord});
442442

443-
MemProfReader Reader(MemProfData);
443+
MemProfReader Reader(std::move(MemProfData));
444444

445445
llvm::SmallVector<MemProfRecord, 1> Records;
446446
for (const auto &KeyRecordPair : Reader) {
@@ -478,7 +478,7 @@ TEST(MemProf, BaseMemProfReaderWithCSIdMap) {
478478
/*MB=*/Block);
479479
MemProfData.Records.insert({F1.hash(), FakeRecord});
480480

481-
MemProfReader Reader(MemProfData);
481+
MemProfReader Reader(std::move(MemProfData));
482482

483483
llvm::SmallVector<MemProfRecord, 1> Records;
484484
for (const auto &KeyRecordPair : Reader) {

0 commit comments

Comments
 (0)