[llvm] bb39151 - [MemProf] Support for random hotness when writing profile (#113998)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 29 22:10:37 PDT 2024
Author: Teresa Johnson
Date: 2024-10-29T22:10:33-07:00
New Revision: bb3915149a7c9b1660db9caebfc96343352e8454
URL: https://github.com/llvm/llvm-project/commit/bb3915149a7c9b1660db9caebfc96343352e8454
DIFF: https://github.com/llvm/llvm-project/commit/bb3915149a7c9b1660db9caebfc96343352e8454.diff
LOG: [MemProf] Support for random hotness when writing profile (#113998)
Add support for generating random hotness in the memprof profile writer,
to be used for testing. The random seed is printed to stderr, and an
additional option enables providing a specific seed in order to
reproduce a particular random profile.
Added:
Modified:
llvm/include/llvm/ProfileData/InstrProfWriter.h
llvm/include/llvm/ProfileData/MemProf.h
llvm/lib/ProfileData/InstrProfWriter.cpp
llvm/test/Transforms/PGOProfile/memprof.ll
llvm/tools/llvm-profdata/llvm-profdata.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/ProfileData/InstrProfWriter.h b/llvm/include/llvm/ProfileData/InstrProfWriter.h
index b8b6c684717b05..559549b0a22cc9 100644
--- a/llvm/include/llvm/ProfileData/InstrProfWriter.h
+++ b/llvm/include/llvm/ProfileData/InstrProfWriter.h
@@ -78,12 +78,20 @@ class InstrProfWriter {
// Whether to serialize the full schema.
bool MemProfFullSchema;
+ // Whether to generated random memprof hotness for testing.
+ bool MemprofGenerateRandomHotness;
+
public:
+ // For memprof testing, random hotness can be assigned to the contexts if
+ // MemprofGenerateRandomHotness is enabled. The random seed can be either
+ // provided by MemprofGenerateRandomHotnessSeed, or if that is 0, one will be
+ // generated in the writer using the current time.
InstrProfWriter(
bool Sparse = false, uint64_t TemporalProfTraceReservoirSize = 0,
uint64_t MaxTemporalProfTraceLength = 0, bool WritePrevVersion = false,
memprof::IndexedVersion MemProfVersionRequested = memprof::Version0,
- bool MemProfFullSchema = false);
+ bool MemProfFullSchema = false, bool MemprofGenerateRandomHotness = false,
+ unsigned MemprofGenerateRandomHotnessSeed = 0);
~InstrProfWriter();
StringMap<ProfilingData> &getProfileData() { return FunctionData; }
diff --git a/llvm/include/llvm/ProfileData/MemProf.h b/llvm/include/llvm/ProfileData/MemProf.h
index f8121d35732518..da2cc807370095 100644
--- a/llvm/include/llvm/ProfileData/MemProf.h
+++ b/llvm/include/llvm/ProfileData/MemProf.h
@@ -147,6 +147,15 @@ struct PortableMemInfoBlock {
return Name; \
}
#include "llvm/ProfileData/MIBEntryDef.inc"
+#undef MIBEntryDef
+
+ // Define setters for each type which can be called by the writer.
+#define MIBEntryDef(NameTag, Name, Type) \
+ void set##Name(Type NewVal) { \
+ assert(Schema[llvm::to_underlying(Meta::Name)]); \
+ Name = NewVal; \
+ }
+#include "llvm/ProfileData/MIBEntryDef.inc"
#undef MIBEntryDef
void clear() { *this = PortableMemInfoBlock(); }
diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp
index 1a3721bf103503..f09241681b92a5 100644
--- a/llvm/lib/ProfileData/InstrProfWriter.cpp
+++ b/llvm/lib/ProfileData/InstrProfWriter.cpp
@@ -19,6 +19,7 @@
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/ProfileData/MemProf.h"
#include "llvm/ProfileData/ProfileCommon.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/EndianStream.h"
@@ -184,13 +185,25 @@ class InstrProfRecordWriterTrait {
InstrProfWriter::InstrProfWriter(
bool Sparse, uint64_t TemporalProfTraceReservoirSize,
uint64_t MaxTemporalProfTraceLength, bool WritePrevVersion,
- memprof::IndexedVersion MemProfVersionRequested, bool MemProfFullSchema)
+ memprof::IndexedVersion MemProfVersionRequested, bool MemProfFullSchema,
+ bool MemprofGenerateRandomHotness,
+ unsigned MemprofGenerateRandomHotnessSeed)
: Sparse(Sparse), MaxTemporalProfTraceLength(MaxTemporalProfTraceLength),
TemporalProfTraceReservoirSize(TemporalProfTraceReservoirSize),
InfoObj(new InstrProfRecordWriterTrait()),
WritePrevVersion(WritePrevVersion),
MemProfVersionRequested(MemProfVersionRequested),
- MemProfFullSchema(MemProfFullSchema) {}
+ MemProfFullSchema(MemProfFullSchema),
+ MemprofGenerateRandomHotness(MemprofGenerateRandomHotness) {
+ // Set up the random number seed if requested.
+ if (MemprofGenerateRandomHotness) {
+ unsigned seed = MemprofGenerateRandomHotnessSeed
+ ? MemprofGenerateRandomHotnessSeed
+ : std::time(nullptr);
+ errs() << "random hotness seed = " << seed << "\n";
+ std::srand(seed);
+ }
+}
InstrProfWriter::~InstrProfWriter() { delete InfoObj; }
@@ -273,13 +286,34 @@ void InstrProfWriter::addRecord(StringRef Name, uint64_t Hash,
void InstrProfWriter::addMemProfRecord(
const Function::GUID Id, const memprof::IndexedMemProfRecord &Record) {
- auto [Iter, Inserted] = MemProfData.Records.insert({Id, Record});
+ auto NewRecord = Record;
+ // Provoke random hotness values if requested. We specify the lifetime access
+ // density and lifetime length that will result in a cold or not cold hotness.
+ // See the logic in getAllocType() in Analysis/MemoryProfileInfo.cpp.
+ if (MemprofGenerateRandomHotness) {
+ for (auto &Alloc : NewRecord.AllocSites) {
+ // To get a not cold context, set the lifetime access density to the
+ // maximum value and the lifetime to 0.
+ uint64_t NewTLAD = std::numeric_limits<uint64_t>::max();
+ uint64_t NewTL = 0;
+ bool IsCold = std::rand() % 2;
+ if (IsCold) {
+ // To get a cold context, set the lifetime access density to 0 and the
+ // lifetime to the maximum value.
+ NewTLAD = 0;
+ NewTL = std::numeric_limits<uint64_t>::max();
+ }
+ Alloc.Info.setTotalLifetimeAccessDensity(NewTLAD);
+ Alloc.Info.setTotalLifetime(NewTL);
+ }
+ }
+ auto [Iter, Inserted] = MemProfData.Records.insert({Id, NewRecord});
// If we inserted a new record then we are done.
if (Inserted) {
return;
}
memprof::IndexedMemProfRecord &Existing = Iter->second;
- Existing.merge(Record);
+ Existing.merge(NewRecord);
}
bool InstrProfWriter::addMemProfFrame(const memprof::FrameId Id,
diff --git a/llvm/test/Transforms/PGOProfile/memprof.ll b/llvm/test/Transforms/PGOProfile/memprof.ll
index e1457ca7251ed8..205eeb8878989d 100644
--- a/llvm/test/Transforms/PGOProfile/memprof.ll
+++ b/llvm/test/Transforms/PGOProfile/memprof.ll
@@ -66,6 +66,18 @@
;; Check that the total sizes are reported if requested.
; RUN: opt < %s -passes='memprof-use<profile-filename=%t.memprofdata>' -pgo-warn-missing-function -S -memprof-report-hinted-sizes 2>&1 | FileCheck %s --check-prefixes=TOTALSIZES
+;; Make sure we emit a random hotness seed if requested.
+; RUN: llvm-profdata merge -memprof-random-hotness %S/Inputs/memprof.memprofraw --profiled-binary %S/Inputs/memprof.exe -o %t.memprofdatarand 2>&1 | FileCheck %s --check-prefix=RAND
+; RAND: random hotness seed =
+;; Can't check the exact values, but make sure applying the random profile
+;; succeeds with the same stats
+; RUN: opt < %s -passes='memprof-use<profile-filename=%t.memprofdatarand>' -pgo-warn-missing-function -S -stats 2>&1 | FileCheck %s --check-prefixes=ALL,MEMPROFONLY,MEMPROFSTATS
+
+;; Make sure we use a specific random hotness seed if requested.
+; RUN: llvm-profdata merge -memprof-random-hotness -memprof-random-hotness-seed=1730170724 %S/Inputs/memprof.memprofraw --profiled-binary %S/Inputs/memprof.exe -o %t.memprofdatarand2 2>&1 | FileCheck %s --check-prefix=RAND2
+; RAND2: random hotness seed = 1730170724
+; RUN: opt < %s -passes='memprof-use<profile-filename=%t.memprofdatarand2>' -pgo-warn-missing-function -S -stats 2>&1 | FileCheck %s --check-prefixes=MEMPROFRAND2,ALL,MEMPROFONLY,MEMPROFSTATS
+
; MEMPROFMATCHINFO: MemProf notcold context with id 1093248920606587996 has total profiled size 10 is matched
; MEMPROFMATCHINFO: MemProf notcold context with id 5725971306423925017 has total profiled size 10 is matched
; MEMPROFMATCHINFO: MemProf notcold context with id 6792096022461663180 has total profiled size 10 is matched
@@ -372,6 +384,13 @@ for.end: ; preds = %for.cond
; MEMPROFNOCOLINFO: ![[C10]] = !{i64 -4535090212904553409}
; MEMPROFNOCOLINFO: ![[C11]] = !{i64 3577763375057267810}
+;; For the specific random seed, this is the expected order of hotness
+; MEMPROFRAND2: !"cold"
+; MEMPROFRAND2: !"cold"
+; MEMPROFRAND2: !"cold"
+; MEMPROFRAND2: !"hot"
+; MEMPROFRAND2: !"hot"
+
; MEMPROFSTATS: 8 memprof - Number of alloc contexts in memory profile.
; MEMPROFSTATS: 10 memprof - Number of callsites in memory profile.
; MEMPROFSTATS: 6 memprof - Number of functions having valid memory profile.
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 59f0f1f1fae899..f7023aa966adf6 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -342,6 +342,15 @@ cl::opt<bool> MemProfFullSchema(
"memprof-full-schema", cl::Hidden, cl::sub(MergeSubcommand),
cl::desc("Use the full schema for serialization"), cl::init(false));
+static cl::opt<bool>
+ MemprofGenerateRandomHotness("memprof-random-hotness", cl::init(false),
+ cl::Hidden, cl::sub(MergeSubcommand),
+ cl::desc("Generate random hotness values"));
+static cl::opt<unsigned> MemprofGenerateRandomHotnessSeed(
+ "memprof-random-hotness-seed", cl::init(0), cl::Hidden,
+ cl::sub(MergeSubcommand),
+ cl::desc("Random hotness seed to use (0 to generate new seed)"));
+
// Options specific to overlap subcommand.
cl::opt<std::string> BaseFilename(cl::Positional, cl::Required,
cl::desc("<base profile file>"),
@@ -641,7 +650,8 @@ struct WriterContext {
SmallSet<instrprof_error, 4> &WriterErrorCodes,
uint64_t ReservoirSize = 0, uint64_t MaxTraceLength = 0)
: Writer(IsSparse, ReservoirSize, MaxTraceLength, DoWritePrevVersion,
- MemProfVersionRequested, MemProfFullSchema),
+ MemProfVersionRequested, MemProfFullSchema,
+ MemprofGenerateRandomHotness, MemprofGenerateRandomHotnessSeed),
ErrLock(ErrLock), WriterErrorCodes(WriterErrorCodes) {}
};
More information about the llvm-commits
mailing list