diff options
author | Teresa Johnson <tejohnson@google.com> | 2025-05-28 13:12:41 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-05-28 13:12:41 -0700 |
commit | cc6f446d3865a5e3a6e50e16e670c307a479a110 (patch) | |
tree | 27abc677ea98e7f0c4855f62024b1355bb280ae1 /llvm/unittests/ProfileData/MemProfTest.cpp | |
parent | 02916a432ca6465e2e45f67be94f1c89c9cd425d (diff) | |
download | llvm-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.cpp | 77 |
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 |