aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/ProfileData/MemProfTest.cpp
diff options
context:
space:
mode:
authorTeresa Johnson <tejohnson@google.com>2025-05-28 13:12:41 -0700
committerGitHub <noreply@github.com>2025-05-28 13:12:41 -0700
commitcc6f446d3865a5e3a6e50e16e670c307a479a110 (patch)
tree27abc677ea98e7f0c4855f62024b1355bb280ae1 /llvm/unittests/ProfileData/MemProfTest.cpp
parent02916a432ca6465e2e45f67be94f1c89c9cd425d (diff)
downloadllvm-cc6f446d3865a5e3a6e50e16e670c307a479a110.zip
llvm-cc6f446d3865a5e3a6e50e16e670c307a479a110.tar.gz
llvm-cc6f446d3865a5e3a6e50e16e670c307a479a110.tar.bz2
[MemProf] Add basic summary section support (#141805)
This patch adds support for a basic MemProf summary section, which is built along with the indexed MemProf profile (e.g. when reading the raw or YAML profiles), and serialized through the indexed profile just after the header. Currently only 6 fields are written, specifically the number of contexts (total, cold, hot), and the max context size (cold, warm, hot). To support forwards and backwards compatibility for added fields in the indexed profile, the number of fields serialized first. The code is written to support forwards compatibility (reading newer profiles with additional summary fields), and comments indicate how to implement backwards compatibility (reading older profiles with fewer summary fields) as needed. Support is added to print the summary as YAML comments when displaying both the raw and indexed profiles via `llvm-profdata show`. Because they are YAML comments, the YAML reader ignores these (the summary is always recomputed when building the indexed profile as described above). This necessitated moving some options and a couple of interfaces out of Analysis/MemoryProfileInfo.cpp and into the new ProfileData/MemProfSummary.cpp file, as we need to classify context hotness earlier and also compute context ids to build the summary from older indexed profiles.
Diffstat (limited to 'llvm/unittests/ProfileData/MemProfTest.cpp')
-rw-r--r--llvm/unittests/ProfileData/MemProfTest.cpp77
1 files changed, 77 insertions, 0 deletions
diff --git a/llvm/unittests/ProfileData/MemProfTest.cpp b/llvm/unittests/ProfileData/MemProfTest.cpp
index 7a2c4af..ee06c23 100644
--- a/llvm/unittests/ProfileData/MemProfTest.cpp
+++ b/llvm/unittests/ProfileData/MemProfTest.cpp
@@ -18,14 +18,23 @@
#include "llvm/ProfileData/MemProfData.inc"
#include "llvm/ProfileData/MemProfRadixTree.h"
#include "llvm/ProfileData/MemProfReader.h"
+#include "llvm/ProfileData/MemProfSummary.h"
#include "llvm/Support/raw_ostream.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <initializer_list>
+using namespace llvm;
+
+extern cl::opt<float> MemProfLifetimeAccessDensityColdThreshold;
+extern cl::opt<unsigned> MemProfAveLifetimeColdThreshold;
+extern cl::opt<unsigned> MemProfMinAveLifetimeAccessDensityHotThreshold;
+extern cl::opt<bool> MemProfUseHotHints;
+
namespace llvm {
namespace memprof {
+
namespace {
using ::llvm::DIGlobal;
@@ -859,6 +868,74 @@ TotalLifetimeAccessDensity: 444
...
)YAML");
}
+
+// Test getAllocType helper.
+// Basic checks on the allocation type for values just above and below
+// the thresholds.
+TEST(MemProf, GetAllocType) {
+ const uint64_t AllocCount = 2;
+ // To be cold we require that
+ // ((float)TotalLifetimeAccessDensity) / AllocCount / 100 <
+ // MemProfLifetimeAccessDensityColdThreshold
+ // so compute the ColdTotalLifetimeAccessDensityThreshold at the threshold.
+ const uint64_t ColdTotalLifetimeAccessDensityThreshold =
+ (uint64_t)(MemProfLifetimeAccessDensityColdThreshold * AllocCount * 100);
+ // To be cold we require that
+ // ((float)TotalLifetime) / AllocCount >=
+ // MemProfAveLifetimeColdThreshold * 1000
+ // so compute the TotalLifetime right at the threshold.
+ const uint64_t ColdTotalLifetimeThreshold =
+ MemProfAveLifetimeColdThreshold * AllocCount * 1000;
+ // To be hot we require that
+ // ((float)TotalLifetimeAccessDensity) / AllocCount / 100 >
+ // MemProfMinAveLifetimeAccessDensityHotThreshold
+ // so compute the HotTotalLifetimeAccessDensityThreshold at the threshold.
+ const uint64_t HotTotalLifetimeAccessDensityThreshold =
+ (uint64_t)(MemProfMinAveLifetimeAccessDensityHotThreshold * AllocCount *
+ 100);
+
+ // Make sure the option for detecting hot allocations is set.
+ bool OrigMemProfUseHotHints = MemProfUseHotHints;
+ MemProfUseHotHints = true;
+
+ // Test Hot
+ // More accesses per byte per sec than hot threshold is hot.
+ EXPECT_EQ(getAllocType(HotTotalLifetimeAccessDensityThreshold + 1, AllocCount,
+ ColdTotalLifetimeThreshold + 1),
+ AllocationType::Hot);
+
+ // Restore original option value.
+ MemProfUseHotHints = OrigMemProfUseHotHints;
+
+ // Without MemProfUseHotHints (default) we should treat simply as NotCold.
+ EXPECT_EQ(getAllocType(HotTotalLifetimeAccessDensityThreshold + 1, AllocCount,
+ ColdTotalLifetimeThreshold + 1),
+ AllocationType::NotCold);
+
+ // Test Cold
+ // Long lived with less accesses per byte per sec than cold threshold is cold.
+ EXPECT_EQ(getAllocType(ColdTotalLifetimeAccessDensityThreshold - 1,
+ AllocCount, ColdTotalLifetimeThreshold + 1),
+ AllocationType::Cold);
+
+ // Test NotCold
+ // Long lived with more accesses per byte per sec than cold threshold is not
+ // cold.
+ EXPECT_EQ(getAllocType(ColdTotalLifetimeAccessDensityThreshold + 1,
+ AllocCount, ColdTotalLifetimeThreshold + 1),
+ AllocationType::NotCold);
+ // Short lived with more accesses per byte per sec than cold threshold is not
+ // cold.
+ EXPECT_EQ(getAllocType(ColdTotalLifetimeAccessDensityThreshold + 1,
+ AllocCount, ColdTotalLifetimeThreshold - 1),
+ AllocationType::NotCold);
+ // Short lived with less accesses per byte per sec than cold threshold is not
+ // cold.
+ EXPECT_EQ(getAllocType(ColdTotalLifetimeAccessDensityThreshold - 1,
+ AllocCount, ColdTotalLifetimeThreshold - 1),
+ AllocationType::NotCold);
+}
+
} // namespace
} // namespace memprof
} // namespace llvm