aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/ProfileData/MemProfTest.cpp
diff options
context:
space:
mode:
authorKazu Hirata <kazu@google.com>2024-04-16 10:16:48 -0700
committerGitHub <noreply@github.com>2024-04-16 10:16:48 -0700
commit8137bd9e03d636a27701a85b6efe899f9571cac5 (patch)
tree3684fa2c1cdb00ac85b9a83ac772c6831fd49c46 /llvm/unittests/ProfileData/MemProfTest.cpp
parent22bba85d82637d0446928ff6ff41f98583f3d3b2 (diff)
downloadllvm-8137bd9e03d636a27701a85b6efe899f9571cac5.zip
llvm-8137bd9e03d636a27701a85b6efe899f9571cac5.tar.gz
llvm-8137bd9e03d636a27701a85b6efe899f9571cac5.tar.bz2
[memprof] Use CSId to construct MemProfRecord (#88362)
We are in the process of referring to call stacks with CallStackId in IndexedMemProfRecord and IndexedAllocationInfo instead of holding call stacks inline (both in memory and the serialized format). Doing so deduplicates call stacks and reduces the MemProf profile file size. Before we can eliminate the two fields holding call stacks inline: - IndexedAllocationInfo::CallStack - IndexedMemProfRecord::CallSites we need to eliminate all the read operations on them. This patch is a step toward that direction. Specifically, we eliminate the read operations in the context of MemProfReader and RawMemProfReader. A subsequent patch will eliminate the read operations during the serialization.
Diffstat (limited to 'llvm/unittests/ProfileData/MemProfTest.cpp')
-rw-r--r--llvm/unittests/ProfileData/MemProfTest.cpp85
1 files changed, 85 insertions, 0 deletions
diff --git a/llvm/unittests/ProfileData/MemProfTest.cpp b/llvm/unittests/ProfileData/MemProfTest.cpp
index 9cf3074..ab9227e9 100644
--- a/llvm/unittests/ProfileData/MemProfTest.cpp
+++ b/llvm/unittests/ProfileData/MemProfTest.cpp
@@ -21,9 +21,11 @@ using ::llvm::DILineInfo;
using ::llvm::DILineInfoSpecifier;
using ::llvm::DILocal;
using ::llvm::StringRef;
+using ::llvm::memprof::CallStackId;
using ::llvm::memprof::CallStackMap;
using ::llvm::memprof::Frame;
using ::llvm::memprof::FrameId;
+using ::llvm::memprof::IndexedAllocationInfo;
using ::llvm::memprof::IndexedMemProfRecord;
using ::llvm::memprof::MemInfoBlock;
using ::llvm::memprof::MemProfReader;
@@ -36,6 +38,7 @@ using ::llvm::memprof::SegmentEntry;
using ::llvm::object::SectionedAddress;
using ::llvm::symbolize::SymbolizableModule;
using ::testing::Return;
+using ::testing::SizeIs;
class MockSymbolizer : public SymbolizableModule {
public:
@@ -432,4 +435,86 @@ TEST(MemProf, BaseMemProfReader) {
EXPECT_THAT(Records[0].AllocSites[0].CallStack[1],
FrameContains("bar", 10U, 2U, false));
}
+
+TEST(MemProf, IndexedMemProfRecordToMemProfRecord) {
+ // Verify that MemProfRecord can be constructed from IndexedMemProfRecord with
+ // CallStackIds only.
+
+ llvm::DenseMap<FrameId, Frame> FrameIdMap;
+ Frame F1(1, 0, 0, false);
+ Frame F2(2, 0, 0, false);
+ Frame F3(3, 0, 0, false);
+ Frame F4(4, 0, 0, false);
+ FrameIdMap.insert({F1.hash(), F1});
+ FrameIdMap.insert({F2.hash(), F2});
+ FrameIdMap.insert({F3.hash(), F3});
+ FrameIdMap.insert({F4.hash(), F4});
+
+ llvm::DenseMap<CallStackId, llvm::SmallVector<FrameId>> CallStackIdMap;
+ llvm::SmallVector<FrameId> CS1 = {F1.hash(), F2.hash()};
+ llvm::SmallVector<FrameId> CS2 = {F1.hash(), F3.hash()};
+ llvm::SmallVector<FrameId> CS3 = {F2.hash(), F3.hash()};
+ llvm::SmallVector<FrameId> CS4 = {F2.hash(), F4.hash()};
+ CallStackIdMap.insert({llvm::memprof::hashCallStack(CS1), CS1});
+ CallStackIdMap.insert({llvm::memprof::hashCallStack(CS2), CS2});
+ CallStackIdMap.insert({llvm::memprof::hashCallStack(CS3), CS3});
+ CallStackIdMap.insert({llvm::memprof::hashCallStack(CS4), CS4});
+
+ IndexedMemProfRecord IndexedRecord;
+ IndexedAllocationInfo AI;
+ AI.CSId = llvm::memprof::hashCallStack(CS1);
+ IndexedRecord.AllocSites.push_back(AI);
+ AI.CSId = llvm::memprof::hashCallStack(CS2);
+ IndexedRecord.AllocSites.push_back(AI);
+ IndexedRecord.CallSiteIds.push_back(llvm::memprof::hashCallStack(CS3));
+ IndexedRecord.CallSiteIds.push_back(llvm::memprof::hashCallStack(CS4));
+
+ bool CSIdMissing = false;
+ bool FrameIdMissing = false;
+
+ auto Callback = [&](CallStackId CSId) -> llvm::SmallVector<Frame> {
+ llvm::SmallVector<Frame> CallStack;
+ llvm::SmallVector<FrameId> FrameIds;
+
+ auto Iter = CallStackIdMap.find(CSId);
+ if (Iter == CallStackIdMap.end())
+ CSIdMissing = true;
+ else
+ FrameIds = Iter->second;
+
+ for (FrameId Id : FrameIds) {
+ Frame F(0, 0, 0, false);
+ auto Iter = FrameIdMap.find(Id);
+ if (Iter == FrameIdMap.end())
+ FrameIdMissing = true;
+ else
+ F = Iter->second;
+ CallStack.push_back(F);
+ }
+
+ return CallStack;
+ };
+
+ MemProfRecord Record = IndexedRecord.toMemProfRecord(Callback);
+
+ // Make sure that all lookups are successful.
+ ASSERT_FALSE(CSIdMissing);
+ ASSERT_FALSE(FrameIdMissing);
+
+ // Verify the contents of Record.
+ ASSERT_THAT(Record.AllocSites, SizeIs(2));
+ ASSERT_THAT(Record.AllocSites[0].CallStack, SizeIs(2));
+ EXPECT_EQ(Record.AllocSites[0].CallStack[0].hash(), F1.hash());
+ EXPECT_EQ(Record.AllocSites[0].CallStack[1].hash(), F2.hash());
+ ASSERT_THAT(Record.AllocSites[1].CallStack, SizeIs(2));
+ EXPECT_EQ(Record.AllocSites[1].CallStack[0].hash(), F1.hash());
+ EXPECT_EQ(Record.AllocSites[1].CallStack[1].hash(), F3.hash());
+ ASSERT_THAT(Record.CallSites, SizeIs(2));
+ ASSERT_THAT(Record.CallSites[0], SizeIs(2));
+ EXPECT_EQ(Record.CallSites[0][0].hash(), F2.hash());
+ EXPECT_EQ(Record.CallSites[0][1].hash(), F3.hash());
+ ASSERT_THAT(Record.CallSites[1], SizeIs(2));
+ EXPECT_EQ(Record.CallSites[1][0].hash(), F2.hash());
+ EXPECT_EQ(Record.CallSites[1][1].hash(), F4.hash());
+}
} // namespace