[llvm] [memprof] Accept a function name in YAML (PR #119453)
Kazu Hirata via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 10 12:46:23 PST 2024
https://github.com/kazutakahirata created https://github.com/llvm/llvm-project/pull/119453
This patch does two things:
- During deserialization, we accept a function name as an alternative
to the usual GUID represented as a hexadecimal number.
- During serialization, we print a GUID as a 16-digit hexadecimal
number prefixed with 0x in the usual way. (Without this patch, we
print a decimal number, which is not customary.)
In YAML, the MemProf profile is a vector of pairs of GUID and
MemProfRecord. This patch accepts a function name for the GUID, but
it does not accept a function name for the GUID used in Frames yet.
That will be addressed in a subsequent patch.
>From 69dc5341f2cb0dc548dc991f471a912f89a039dd Mon Sep 17 00:00:00 2001
From: Kazu Hirata <kazu at google.com>
Date: Mon, 9 Dec 2024 23:02:36 -0800
Subject: [PATCH] [memprof] Accept a function name in YAML
This patch does two things:
- During deserialization, we accept a function name as an alternative
to the usual GUID represented as a hexadecimal number.
- During serialization, we print a GUID as a 16-digit hexadecimal
number prefixed with 0x in the usual way. (Without this patch, we
print a decimal number, which is not customary.)
In YAML, the MemProf profile is a vector of pairs of GUID and
MemProfRecord. This patch accepts a function name for the GUID, but
it does not accept a function name for the GUID used in Frames yet.
That will be addressed in a subsequent patch.
---
llvm/include/llvm/ProfileData/MemProf.h | 28 +++++++++++++-
.../tools/llvm-profdata/memprof-yaml.test | 2 +-
llvm/unittests/ProfileData/MemProfTest.cpp | 38 +++++++++++++++++++
3 files changed, 66 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/ProfileData/MemProf.h b/llvm/include/llvm/ProfileData/MemProf.h
index 8a85196e57044d..a4d8b5479061d5 100644
--- a/llvm/include/llvm/ProfileData/MemProf.h
+++ b/llvm/include/llvm/ProfileData/MemProf.h
@@ -11,6 +11,7 @@
#include "llvm/Support/BLAKE3.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/HashBuilder.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
@@ -491,11 +492,15 @@ struct MemProfRecord {
}
};
+// A "typedef" for GUID. See ScalarTraits<memprof::GUIDHex64> for how a GUID is
+// serialized and deserialized in YAML.
+LLVM_YAML_STRONG_TYPEDEF(uint64_t, GUIDHex64)
+
// Helper struct for AllMemProfData. In YAML, we treat the GUID and the fields
// within MemProfRecord at the same level as if the GUID were part of
// MemProfRecord.
struct GUIDMemProfRecordPair {
- GlobalValue::GUID GUID;
+ GUIDHex64 GUID;
MemProfRecord Record;
};
@@ -1166,6 +1171,27 @@ template <typename FrameIdTy> class CallStackRadixTreeBuilder {
} // namespace memprof
namespace yaml {
+template <> struct ScalarTraits<memprof::GUIDHex64> {
+ static void output(const memprof::GUIDHex64 &Val, void *, raw_ostream &Out) {
+ // Print GUID as a 16-digit hexadecimal number.
+ Out << format("0x%016" PRIx64, (uint64_t)Val);
+ }
+ static StringRef input(StringRef Scalar, void *, memprof::GUIDHex64 &Val) {
+ uint64_t Num;
+ if (Scalar.starts_with_insensitive("0x")) {
+ // Accept hexadecimal numbers starting with 0x or 0X.
+ if (Scalar.getAsInteger(0, Num))
+ return "invalid hex64 number";
+ Val = Num;
+ } else {
+ // Otherwise, treat the input as a string containing a function name.
+ Val = memprof::IndexedMemProfRecord::getGUID(Scalar);
+ }
+ return StringRef();
+ }
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
template <> struct MappingTraits<memprof::Frame> {
static void mapping(IO &Io, memprof::Frame &F) {
Io.mapRequired("Function", F.Function);
diff --git a/llvm/test/tools/llvm-profdata/memprof-yaml.test b/llvm/test/tools/llvm-profdata/memprof-yaml.test
index fbbf8a6e7e5b52..0c040ab3a1f9d9 100644
--- a/llvm/test/tools/llvm-profdata/memprof-yaml.test
+++ b/llvm/test/tools/llvm-profdata/memprof-yaml.test
@@ -8,7 +8,7 @@
;--- memprof-in.yaml
---
HeapProfileRecords:
- - GUID: 16045690981402826360
+ - GUID: 0xdeadbeef12345678
AllocSites:
- Callstack:
- { Function: 100, LineOffset: 11, Column: 10, IsInlineFrame: true }
diff --git a/llvm/unittests/ProfileData/MemProfTest.cpp b/llvm/unittests/ProfileData/MemProfTest.cpp
index 093b3a26b5f872..bd9a2d0c5d6292 100644
--- a/llvm/unittests/ProfileData/MemProfTest.cpp
+++ b/llvm/unittests/ProfileData/MemProfTest.cpp
@@ -35,6 +35,7 @@ using ::llvm::StringRef;
using ::llvm::object::SectionedAddress;
using ::llvm::symbolize::SymbolizableModule;
using ::testing::ElementsAre;
+using ::testing::IsEmpty;
using ::testing::Pair;
using ::testing::Return;
using ::testing::SizeIs;
@@ -760,6 +761,43 @@ TEST(MemProf, YAMLParser) {
ElementsAre(hashCallStack(CS3), hashCallStack(CS4)));
}
+// Verify that the YAML parser accepts a GUID expressed as a function name.
+TEST(MemProf, YAMLParserGUID) {
+ StringRef YAMLData = R"YAML(
+---
+HeapProfileRecords:
+- GUID: _Z3fooi
+ AllocSites:
+ - Callstack:
+ - {Function: 0x100, LineOffset: 11, Column: 10, IsInlineFrame: true}
+ MemInfoBlock: {}
+ CallSites: []
+)YAML";
+
+ YAMLMemProfReader YAMLReader;
+ YAMLReader.parse(YAMLData);
+ IndexedMemProfData MemProfData = YAMLReader.takeMemProfData();
+
+ Frame F1(0x100, 11, 10, true);
+
+ llvm::SmallVector<FrameId> CS1 = {F1.hash()};
+
+ // Verify the entire contents of MemProfData.Frames.
+ EXPECT_THAT(MemProfData.Frames, UnorderedElementsAre(Pair(F1.hash(), F1)));
+
+ // Verify the entire contents of MemProfData.Frames.
+ EXPECT_THAT(MemProfData.CallStacks,
+ UnorderedElementsAre(Pair(hashCallStack(CS1), CS1)));
+
+ // Verify the entire contents of MemProfData.Records.
+ ASSERT_THAT(MemProfData.Records, SizeIs(1));
+ const auto &[GUID, Record] = *MemProfData.Records.begin();
+ EXPECT_EQ(GUID, IndexedMemProfRecord::getGUID("_Z3fooi"));
+ ASSERT_THAT(Record.AllocSites, SizeIs(1));
+ EXPECT_EQ(Record.AllocSites[0].CSId, hashCallStack(CS1));
+ EXPECT_THAT(Record.CallSiteIds, IsEmpty());
+}
+
template <typename T> std::string serializeInYAML(T &Val) {
std::string Out;
llvm::raw_string_ostream OS(Out);
More information about the llvm-commits
mailing list