Skip to content

Commit edf733b

Browse files
[memprof] Take Schema into account in PortableMemInfoBlock::serializedSize (#89824)
PortableMemInfoBlock::{serialize,deserialize} take Schema into account, allowing us to serialize/deserialize a subset of the fields. However, PortableMemInfoBlock::serializedSize does not. That is, it assumes that all fields are always serialized and deserialized. In other words, if we choose to serialize/deserialize a subset of the fields, serializedSize would claim more storage than we actually need. This patch fixes the problem by teaching serializedSize to take Schema into account. For now, this patch has no effect on the actual indexed MemProf profile because we serialize/deserialize all fields, but that might change in the future. Aside from check-llvm, I tested this patch by verifying that llvm-profdata generates bit-wise identical files for each version for a large raw MemProf file I have.
1 parent 4e9decf commit edf733b

File tree

2 files changed

+40
-21
lines changed

2 files changed

+40
-21
lines changed

llvm/include/llvm/ProfileData/MemProf.h

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,22 @@ struct PortableMemInfoBlock {
138138
return !operator==(Other);
139139
}
140140

141-
static constexpr size_t serializedSize() {
141+
static size_t serializedSize(const MemProfSchema &Schema) {
142142
size_t Result = 0;
143-
#define MIBEntryDef(NameTag, Name, Type) Result += sizeof(Type);
143+
144+
for (const Meta Id : Schema) {
145+
switch (Id) {
146+
#define MIBEntryDef(NameTag, Name, Type) \
147+
case Meta::Name: { \
148+
Result += sizeof(Type); \
149+
} break;
144150
#include "llvm/ProfileData/MIBEntryDef.inc"
145151
#undef MIBEntryDef
152+
default:
153+
llvm_unreachable("Unknown meta type id, invalid input?");
154+
}
155+
}
156+
146157
return Result;
147158
}
148159

@@ -292,7 +303,8 @@ struct IndexedAllocationInfo {
292303
: CallStack(CS.begin(), CS.end()), CSId(CSId), Info(MB) {}
293304

294305
// Returns the size in bytes when this allocation info struct is serialized.
295-
size_t serializedSize(IndexedVersion Version) const;
306+
size_t serializedSize(const MemProfSchema &Schema,
307+
IndexedVersion Version) const;
296308

297309
bool operator==(const IndexedAllocationInfo &Other) const {
298310
if (Other.Info != Info)
@@ -367,7 +379,8 @@ struct IndexedMemProfRecord {
367379
CallSites.append(Other.CallSites);
368380
}
369381

370-
size_t serializedSize(IndexedVersion Version) const;
382+
size_t serializedSize(const MemProfSchema &Schema,
383+
IndexedVersion Version) const;
371384

372385
bool operator==(const IndexedMemProfRecord &Other) const {
373386
if (Other.AllocSites != AllocSites)
@@ -535,7 +548,7 @@ class RecordWriterTrait {
535548
endian::Writer LE(Out, llvm::endianness::little);
536549
offset_type N = sizeof(K);
537550
LE.write<offset_type>(N);
538-
offset_type M = V.serializedSize(Version);
551+
offset_type M = V.serializedSize(*Schema, Version);
539552
LE.write<offset_type>(M);
540553
return std::make_pair(N, M);
541554
}

llvm/lib/ProfileData/MemProf.cpp

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,42 +10,46 @@
1010

1111
namespace llvm {
1212
namespace memprof {
13-
static size_t serializedSizeV0(const IndexedAllocationInfo &IAI) {
13+
static size_t serializedSizeV0(const IndexedAllocationInfo &IAI,
14+
const MemProfSchema &Schema) {
1415
size_t Size = 0;
1516
// The number of frames to serialize.
1617
Size += sizeof(uint64_t);
1718
// The callstack frame ids.
1819
Size += sizeof(FrameId) * IAI.CallStack.size();
1920
// The size of the payload.
20-
Size += PortableMemInfoBlock::serializedSize();
21+
Size += PortableMemInfoBlock::serializedSize(Schema);
2122
return Size;
2223
}
2324

24-
static size_t serializedSizeV2(const IndexedAllocationInfo &IAI) {
25+
static size_t serializedSizeV2(const IndexedAllocationInfo &IAI,
26+
const MemProfSchema &Schema) {
2527
size_t Size = 0;
2628
// The CallStackId
2729
Size += sizeof(CallStackId);
2830
// The size of the payload.
29-
Size += PortableMemInfoBlock::serializedSize();
31+
Size += PortableMemInfoBlock::serializedSize(Schema);
3032
return Size;
3133
}
3234

33-
size_t IndexedAllocationInfo::serializedSize(IndexedVersion Version) const {
35+
size_t IndexedAllocationInfo::serializedSize(const MemProfSchema &Schema,
36+
IndexedVersion Version) const {
3437
switch (Version) {
3538
case Version0:
3639
case Version1:
37-
return serializedSizeV0(*this);
40+
return serializedSizeV0(*this, Schema);
3841
case Version2:
39-
return serializedSizeV2(*this);
42+
return serializedSizeV2(*this, Schema);
4043
}
4144
llvm_unreachable("unsupported MemProf version");
4245
}
4346

44-
static size_t serializedSizeV0(const IndexedMemProfRecord &Record) {
47+
static size_t serializedSizeV0(const IndexedMemProfRecord &Record,
48+
const MemProfSchema &Schema) {
4549
// The number of alloc sites to serialize.
4650
size_t Result = sizeof(uint64_t);
4751
for (const IndexedAllocationInfo &N : Record.AllocSites)
48-
Result += N.serializedSize(Version0);
52+
Result += N.serializedSize(Schema, Version0);
4953

5054
// The number of callsites we have information for.
5155
Result += sizeof(uint64_t);
@@ -57,11 +61,12 @@ static size_t serializedSizeV0(const IndexedMemProfRecord &Record) {
5761
return Result;
5862
}
5963

60-
static size_t serializedSizeV2(const IndexedMemProfRecord &Record) {
64+
static size_t serializedSizeV2(const IndexedMemProfRecord &Record,
65+
const MemProfSchema &Schema) {
6166
// The number of alloc sites to serialize.
6267
size_t Result = sizeof(uint64_t);
6368
for (const IndexedAllocationInfo &N : Record.AllocSites)
64-
Result += N.serializedSize(Version2);
69+
Result += N.serializedSize(Schema, Version2);
6570

6671
// The number of callsites we have information for.
6772
Result += sizeof(uint64_t);
@@ -70,13 +75,14 @@ static size_t serializedSizeV2(const IndexedMemProfRecord &Record) {
7075
return Result;
7176
}
7277

73-
size_t IndexedMemProfRecord::serializedSize(IndexedVersion Version) const {
78+
size_t IndexedMemProfRecord::serializedSize(const MemProfSchema &Schema,
79+
IndexedVersion Version) const {
7480
switch (Version) {
7581
case Version0:
7682
case Version1:
77-
return serializedSizeV0(*this);
83+
return serializedSizeV0(*this, Schema);
7884
case Version2:
79-
return serializedSizeV2(*this);
85+
return serializedSizeV2(*this, Schema);
8086
}
8187
llvm_unreachable("unsupported MemProf version");
8288
}
@@ -156,7 +162,7 @@ static IndexedMemProfRecord deserializeV0(const MemProfSchema &Schema,
156162
}
157163
Node.CSId = hashCallStack(Node.CallStack);
158164
Node.Info.deserialize(Schema, Ptr);
159-
Ptr += PortableMemInfoBlock::serializedSize();
165+
Ptr += PortableMemInfoBlock::serializedSize(Schema);
160166
Record.AllocSites.push_back(Node);
161167
}
162168

@@ -193,7 +199,7 @@ static IndexedMemProfRecord deserializeV2(const MemProfSchema &Schema,
193199
IndexedAllocationInfo Node;
194200
Node.CSId = endian::readNext<CallStackId, llvm::endianness::little>(Ptr);
195201
Node.Info.deserialize(Schema, Ptr);
196-
Ptr += PortableMemInfoBlock::serializedSize();
202+
Ptr += PortableMemInfoBlock::serializedSize(Schema);
197203
Record.AllocSites.push_back(Node);
198204
}
199205

0 commit comments

Comments
 (0)