Skip to content

Commit 9def83c

Browse files
committed
[memprof] Refactor out the MemInfoBlock into a macro based def.
This patch refactors out the MemInfoBlock definition into a macro based header which can be included to generate enums, structus and code for each field recorded by the memprof profiling runtime. Differential Revision: https://reviews.llvm.org/D117722
1 parent fb40a61 commit 9def83c

File tree

8 files changed

+283
-163
lines changed

8 files changed

+283
-163
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*===-- MemEntryDef.inc - MemProf profiling runtime macros -*- C++ -*-======== *\
2+
|*
3+
|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
|* See https://llvm.org/LICENSE.txt for license information.
5+
|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
|*
7+
\*===----------------------------------------------------------------------===*/
8+
/*
9+
* This file defines the macros for memprof profiling data structures.
10+
* Eg. usage to define the memprof meminfoblock struct:
11+
*
12+
* struct MemInfoBlock {
13+
* #define MIBEntryDef(NameTag, Name, Type) Type Name;
14+
* #include MIBEntryDef.inc
15+
* #undef MIBEntryDef
16+
* };
17+
*
18+
* This file has two identical copies. The primary copy lives in LLVM and
19+
* the other one sits in compiler-rt/include/profile directory. To make changes
20+
* in this file, first modify the primary copy and copy it over to compiler-rt.
21+
* Testing of any change in this file can start only after the two copies are
22+
* synced up.
23+
*
24+
\*===----------------------------------------------------------------------===*/
25+
26+
#ifndef MIBEntryDef
27+
#define MIBEntryDef(NameTag, Name, Type)
28+
#endif
29+
30+
MIBEntryDef(AllocCount = 1, AllocCount, uint32_t)
31+
MIBEntryDef(TotalAccessCount = 2, TotalAccessCount, uint64_t)
32+
MIBEntryDef(MinAccessCount = 3, MinAccessCount, uint64_t)
33+
MIBEntryDef(MaxAccessCount = 4, MaxAccessCount, uint64_t)
34+
MIBEntryDef(TotalSize = 5, TotalSize, uint64_t)
35+
MIBEntryDef(MinSize = 6, MinSize, uint32_t)
36+
MIBEntryDef(MaxSize = 7, MaxSize, uint32_t)
37+
MIBEntryDef(AllocTimestamp = 8, AllocTimestamp, uint32_t)
38+
MIBEntryDef(DeallocTimestamp = 9, DeallocTimestamp, uint32_t)
39+
MIBEntryDef(TotalLifetime = 10, TotalLifetime, uint64_t)
40+
MIBEntryDef(MinLifetime = 11, MinLifetime, uint32_t)
41+
MIBEntryDef(MaxLifetime = 12, MaxLifetime, uint32_t)
42+
MIBEntryDef(AllocCpuId = 13, AllocCpuId, uint32_t)
43+
MIBEntryDef(DeallocCpuId = 14, DeallocCpuId, uint32_t)
44+
MIBEntryDef(NumMigratedCpu = 15, NumMigratedCpu, uint32_t)
45+
MIBEntryDef(NumLifetimeOverlaps = 16, NumLifetimeOverlaps, uint32_t)
46+
MIBEntryDef(NumSameAllocCpu = 17, NumSameAllocCpu, uint32_t)
47+
MIBEntryDef(NumSameDeallocCpu = 18, NumSameDeallocCpu, uint32_t)
48+
MIBEntryDef(DataTypeId = 19, DataTypeId, uint64_t)
49+
50+
51+

compiler-rt/include/profile/MemProfData.inc

Lines changed: 69 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -80,71 +80,80 @@ PACKED(struct SegmentEntry {
8080
}
8181
});
8282

83+
// Packed struct definition for MSVC. We can't use the PACKED macro defined in
84+
// MemProfData.inc since it would mean we are embedding a directive (the
85+
// #include for MIBEntryDef) into the macros which is undefined behaviour.
86+
#ifdef _MSC_VER
87+
__pragma(pack(push,1))
88+
#endif
89+
8390
// A struct representing the heap allocation characteristics of a particular
8491
// runtime context. This struct is shared between the compiler-rt runtime and
8592
// the raw profile reader. The indexed format uses a separate, self-describing
8693
// backwards compatible format.
87-
PACKED(struct MemInfoBlock {
88-
uint32_t alloc_count;
89-
uint64_t total_access_count, min_access_count, max_access_count;
90-
uint64_t total_size;
91-
uint32_t min_size, max_size;
92-
uint32_t alloc_timestamp, dealloc_timestamp;
93-
uint64_t total_lifetime;
94-
uint32_t min_lifetime, max_lifetime;
95-
uint32_t alloc_cpu_id, dealloc_cpu_id;
96-
uint32_t num_migrated_cpu;
97-
98-
// Only compared to prior deallocated object currently.
99-
uint32_t num_lifetime_overlaps;
100-
uint32_t num_same_alloc_cpu;
101-
uint32_t num_same_dealloc_cpu;
102-
103-
uint64_t data_type_id; // TODO: hash of type name
104-
105-
MemInfoBlock() : alloc_count(0) {}
106-
107-
MemInfoBlock(uint32_t size, uint64_t access_count, uint32_t alloc_timestamp,
108-
uint32_t dealloc_timestamp, uint32_t alloc_cpu, uint32_t dealloc_cpu)
109-
: alloc_count(1), total_access_count(access_count),
110-
min_access_count(access_count), max_access_count(access_count),
111-
total_size(size), min_size(size), max_size(size),
112-
alloc_timestamp(alloc_timestamp), dealloc_timestamp(dealloc_timestamp),
113-
total_lifetime(dealloc_timestamp - alloc_timestamp),
114-
min_lifetime(total_lifetime), max_lifetime(total_lifetime),
115-
alloc_cpu_id(alloc_cpu), dealloc_cpu_id(dealloc_cpu),
116-
num_lifetime_overlaps(0), num_same_alloc_cpu(0),
117-
num_same_dealloc_cpu(0) {
118-
num_migrated_cpu = alloc_cpu_id != dealloc_cpu_id;
119-
}
120-
121-
void Merge(const MemInfoBlock &newMIB) {
122-
alloc_count += newMIB.alloc_count;
123-
124-
total_access_count += newMIB.total_access_count;
125-
min_access_count = newMIB.min_access_count < min_access_count ? newMIB.min_access_count : min_access_count;
126-
max_access_count = newMIB.max_access_count < max_access_count ? newMIB.max_access_count : max_access_count;
127-
128-
total_size += newMIB.total_size;
129-
min_size = newMIB.min_size < min_size ? newMIB.min_size : min_size;
130-
max_size = newMIB.max_size < max_size ? newMIB.max_size : max_size;
94+
struct MemInfoBlock{
95+
96+
#define MIBEntryDef(NameTag, Name, Type) Type Name;
97+
#include "MIBEntryDef.inc"
98+
#undef MIBEntryDef
99+
100+
bool operator==(const MemInfoBlock& Other) const {
101+
bool IsEqual = true;
102+
#define MIBEntryDef(NameTag, Name, Type) \
103+
IsEqual = (IsEqual && Name == Other.Name);
104+
#include "MIBEntryDef.inc"
105+
#undef MIBEntryDef
106+
return IsEqual;
107+
}
108+
109+
MemInfoBlock() : AllocCount(0) {}
110+
111+
MemInfoBlock(uint32_t size, uint64_t access_count, uint32_t alloc_timestamp,
112+
uint32_t dealloc_timestamp, uint32_t alloc_cpu, uint32_t dealloc_cpu)
113+
: AllocCount(1), TotalAccessCount(access_count),
114+
MinAccessCount(access_count), MaxAccessCount(access_count),
115+
TotalSize(size), MinSize(size), MaxSize(size),
116+
AllocTimestamp(alloc_timestamp), DeallocTimestamp(dealloc_timestamp),
117+
TotalLifetime(dealloc_timestamp - alloc_timestamp),
118+
MinLifetime(TotalLifetime), MaxLifetime(TotalLifetime),
119+
AllocCpuId(alloc_cpu), DeallocCpuId(dealloc_cpu),
120+
NumLifetimeOverlaps(0), NumSameAllocCpu(0),
121+
NumSameDeallocCpu(0) {
122+
NumMigratedCpu = AllocCpuId != DeallocCpuId;
123+
}
124+
125+
void Merge(const MemInfoBlock &newMIB) {
126+
AllocCount += newMIB.AllocCount;
127+
128+
TotalAccessCount += newMIB.TotalAccessCount;
129+
MinAccessCount = newMIB.MinAccessCount < MinAccessCount ? newMIB.MinAccessCount : MinAccessCount;
130+
MaxAccessCount = newMIB.MaxAccessCount < MaxAccessCount ? newMIB.MaxAccessCount : MaxAccessCount;
131+
132+
TotalSize += newMIB.TotalSize;
133+
MinSize = newMIB.MinSize < MinSize ? newMIB.MinSize : MinSize;
134+
MaxSize = newMIB.MaxSize < MaxSize ? newMIB.MaxSize : MaxSize;
135+
136+
TotalLifetime += newMIB.TotalLifetime;
137+
MinLifetime = newMIB.MinLifetime < MinLifetime ? newMIB.MinLifetime : MinLifetime;
138+
MaxLifetime = newMIB.MaxLifetime > MaxLifetime ? newMIB.MaxLifetime : MaxLifetime;
139+
140+
// We know newMIB was deallocated later, so just need to check if it was
141+
// allocated before last one deallocated.
142+
NumLifetimeOverlaps += newMIB.AllocTimestamp < DeallocTimestamp;
143+
AllocTimestamp = newMIB.AllocTimestamp;
144+
DeallocTimestamp = newMIB.DeallocTimestamp;
145+
146+
NumSameAllocCpu += AllocCpuId == newMIB.AllocCpuId;
147+
NumSameDeallocCpu += DeallocCpuId == newMIB.DeallocCpuId;
148+
AllocCpuId = newMIB.AllocCpuId;
149+
DeallocCpuId = newMIB.DeallocCpuId;
150+
}
131151

132-
total_lifetime += newMIB.total_lifetime;
133-
min_lifetime = newMIB.min_lifetime < min_lifetime ? newMIB.min_lifetime : min_lifetime;
134-
max_lifetime = newMIB.max_lifetime > max_lifetime ? newMIB.max_lifetime : max_lifetime;
135-
136-
// We know newMIB was deallocated later, so just need to check if it was
137-
// allocated before last one deallocated.
138-
num_lifetime_overlaps += newMIB.alloc_timestamp < dealloc_timestamp;
139-
alloc_timestamp = newMIB.alloc_timestamp;
140-
dealloc_timestamp = newMIB.dealloc_timestamp;
141-
142-
num_same_alloc_cpu += alloc_cpu_id == newMIB.alloc_cpu_id;
143-
num_same_dealloc_cpu += dealloc_cpu_id == newMIB.dealloc_cpu_id;
144-
alloc_cpu_id = newMIB.alloc_cpu_id;
145-
dealloc_cpu_id = newMIB.dealloc_cpu_id;
146-
}
147-
});
152+
#ifdef _MSC_VER
153+
} __pragma(pack(pop));
154+
#else
155+
} __attribute__((__packed__));
156+
#endif
148157

149158
} // namespace memprof
150159
} // namespace llvm

compiler-rt/lib/memprof/memprof_allocator.cpp

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -43,32 +43,32 @@ void Print(const MemInfoBlock &M, const u64 id, bool print_terse) {
4343
u64 p;
4444

4545
if (print_terse) {
46-
p = M.total_size * 100 / M.alloc_count;
47-
Printf("MIB:%llu/%u/%llu.%02llu/%u/%u/", id, M.alloc_count, p / 100,
48-
p % 100, M.min_size, M.max_size);
49-
p = M.total_access_count * 100 / M.alloc_count;
50-
Printf("%llu.%02llu/%llu/%llu/", p / 100, p % 100, M.min_access_count,
51-
M.max_access_count);
52-
p = M.total_lifetime * 100 / M.alloc_count;
53-
Printf("%llu.%02llu/%u/%u/", p / 100, p % 100, M.min_lifetime,
54-
M.max_lifetime);
55-
Printf("%u/%u/%u/%u\n", M.num_migrated_cpu, M.num_lifetime_overlaps,
56-
M.num_same_alloc_cpu, M.num_same_dealloc_cpu);
46+
p = M.TotalSize * 100 / M.AllocCount;
47+
Printf("MIB:%llu/%u/%llu.%02llu/%u/%u/", id, M.AllocCount, p / 100, p % 100,
48+
M.MinSize, M.MaxSize);
49+
p = M.TotalAccessCount * 100 / M.AllocCount;
50+
Printf("%llu.%02llu/%llu/%llu/", p / 100, p % 100, M.MinAccessCount,
51+
M.MaxAccessCount);
52+
p = M.TotalLifetime * 100 / M.AllocCount;
53+
Printf("%llu.%02llu/%u/%u/", p / 100, p % 100, M.MinLifetime,
54+
M.MaxLifetime);
55+
Printf("%u/%u/%u/%u\n", M.NumMigratedCpu, M.NumLifetimeOverlaps,
56+
M.NumSameAllocCpu, M.NumSameDeallocCpu);
5757
} else {
58-
p = M.total_size * 100 / M.alloc_count;
58+
p = M.TotalSize * 100 / M.AllocCount;
5959
Printf("Memory allocation stack id = %llu\n", id);
6060
Printf("\talloc_count %u, size (ave/min/max) %llu.%02llu / %u / %u\n",
61-
M.alloc_count, p / 100, p % 100, M.min_size, M.max_size);
62-
p = M.total_access_count * 100 / M.alloc_count;
61+
M.AllocCount, p / 100, p % 100, M.MinSize, M.MaxSize);
62+
p = M.TotalAccessCount * 100 / M.AllocCount;
6363
Printf("\taccess_count (ave/min/max): %llu.%02llu / %llu / %llu\n", p / 100,
64-
p % 100, M.min_access_count, M.max_access_count);
65-
p = M.total_lifetime * 100 / M.alloc_count;
64+
p % 100, M.MinAccessCount, M.MaxAccessCount);
65+
p = M.TotalLifetime * 100 / M.AllocCount;
6666
Printf("\tlifetime (ave/min/max): %llu.%02llu / %u / %u\n", p / 100,
67-
p % 100, M.min_lifetime, M.max_lifetime);
67+
p % 100, M.MinLifetime, M.MaxLifetime);
6868
Printf("\tnum migrated: %u, num lifetime overlaps: %u, num same alloc "
6969
"cpu: %u, num same dealloc_cpu: %u\n",
70-
M.num_migrated_cpu, M.num_lifetime_overlaps, M.num_same_alloc_cpu,
71-
M.num_same_dealloc_cpu);
70+
M.NumMigratedCpu, M.NumLifetimeOverlaps, M.NumSameAllocCpu,
71+
M.NumSameDeallocCpu);
7272
}
7373
}
7474
} // namespace

compiler-rt/lib/memprof/tests/rawprofile.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ TEST(MemProf, Basic) {
8282
// Since we want to override the constructor set vals to make it easier to
8383
// test.
8484
memset(&FakeMIB, 0, sizeof(MemInfoBlock));
85-
FakeMIB.alloc_count = 0x1;
86-
FakeMIB.total_access_count = 0x2;
85+
FakeMIB.AllocCount = 0x1;
86+
FakeMIB.TotalAccessCount = 0x2;
8787

8888
uint64_t FakeIds[2];
8989
FakeIds[0] = PopulateFakeMap(FakeMIB, /*StackPCBegin=*/2, FakeMap);
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*===-- MemEntryDef.inc - MemProf profiling runtime macros -*- C++ -*-======== *\
2+
|*
3+
|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
|* See https://llvm.org/LICENSE.txt for license information.
5+
|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
|*
7+
\*===----------------------------------------------------------------------===*/
8+
/*
9+
* This file defines the macros for memprof profiling data structures.
10+
* Eg. usage to define the memprof meminfoblock struct:
11+
*
12+
* struct MemInfoBlock {
13+
* #define MIBEntryDef(NameTag, Name, Type) Type Name;
14+
* #include MIBEntryDef.inc
15+
* #undef MIBEntryDef
16+
* };
17+
*
18+
* This file has two identical copies. The primary copy lives in LLVM and
19+
* the other one sits in compiler-rt/include/profile directory. To make changes
20+
* in this file, first modify the primary copy and copy it over to compiler-rt.
21+
* Testing of any change in this file can start only after the two copies are
22+
* synced up.
23+
*
24+
\*===----------------------------------------------------------------------===*/
25+
26+
#ifndef MIBEntryDef
27+
#define MIBEntryDef(NameTag, Name, Type)
28+
#endif
29+
30+
MIBEntryDef(AllocCount = 1, AllocCount, uint32_t)
31+
MIBEntryDef(TotalAccessCount = 2, TotalAccessCount, uint64_t)
32+
MIBEntryDef(MinAccessCount = 3, MinAccessCount, uint64_t)
33+
MIBEntryDef(MaxAccessCount = 4, MaxAccessCount, uint64_t)
34+
MIBEntryDef(TotalSize = 5, TotalSize, uint64_t)
35+
MIBEntryDef(MinSize = 6, MinSize, uint32_t)
36+
MIBEntryDef(MaxSize = 7, MaxSize, uint32_t)
37+
MIBEntryDef(AllocTimestamp = 8, AllocTimestamp, uint32_t)
38+
MIBEntryDef(DeallocTimestamp = 9, DeallocTimestamp, uint32_t)
39+
MIBEntryDef(TotalLifetime = 10, TotalLifetime, uint64_t)
40+
MIBEntryDef(MinLifetime = 11, MinLifetime, uint32_t)
41+
MIBEntryDef(MaxLifetime = 12, MaxLifetime, uint32_t)
42+
MIBEntryDef(AllocCpuId = 13, AllocCpuId, uint32_t)
43+
MIBEntryDef(DeallocCpuId = 14, DeallocCpuId, uint32_t)
44+
MIBEntryDef(NumMigratedCpu = 15, NumMigratedCpu, uint32_t)
45+
MIBEntryDef(NumLifetimeOverlaps = 16, NumLifetimeOverlaps, uint32_t)
46+
MIBEntryDef(NumSameAllocCpu = 17, NumSameAllocCpu, uint32_t)
47+
MIBEntryDef(NumSameDeallocCpu = 18, NumSameDeallocCpu, uint32_t)
48+
MIBEntryDef(DataTypeId = 19, DataTypeId, uint64_t)
49+
50+
51+

llvm/include/llvm/ProfileData/MemProf.h

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -51,41 +51,41 @@ struct MemProfRecord {
5151

5252
// TODO: Replace this once the format is updated to be version agnostic.
5353
OS << " "
54-
<< "AllocCount: " << Info.alloc_count << "\n";
54+
<< "AllocCount: " << Info.AllocCount << "\n";
5555
OS << " "
56-
<< "TotalAccessCount: " << Info.total_access_count << "\n";
56+
<< "TotalAccessCount: " << Info.TotalAccessCount << "\n";
5757
OS << " "
58-
<< "MinAccessCount: " << Info.min_access_count << "\n";
58+
<< "MinAccessCount: " << Info.MinAccessCount << "\n";
5959
OS << " "
60-
<< "MaxAccessCount: " << Info.max_access_count << "\n";
60+
<< "MaxAccessCount: " << Info.MaxAccessCount << "\n";
6161
OS << " "
62-
<< "TotalSize: " << Info.total_size << "\n";
62+
<< "TotalSize: " << Info.TotalSize << "\n";
6363
OS << " "
64-
<< "MinSize: " << Info.min_size << "\n";
64+
<< "MinSize: " << Info.MinSize << "\n";
6565
OS << " "
66-
<< "MaxSize: " << Info.max_size << "\n";
66+
<< "MaxSize: " << Info.MaxSize << "\n";
6767
OS << " "
68-
<< "AllocTimestamp: " << Info.alloc_timestamp << "\n";
68+
<< "AllocTimestamp: " << Info.AllocTimestamp << "\n";
6969
OS << " "
70-
<< "DeallocTimestamp: " << Info.dealloc_timestamp << "\n";
70+
<< "DeallocTimestamp: " << Info.DeallocTimestamp << "\n";
7171
OS << " "
72-
<< "TotalLifetime: " << Info.total_lifetime << "\n";
72+
<< "TotalLifetime: " << Info.TotalLifetime << "\n";
7373
OS << " "
74-
<< "MinLifetime: " << Info.min_lifetime << "\n";
74+
<< "MinLifetime: " << Info.MinLifetime << "\n";
7575
OS << " "
76-
<< "MaxLifetime: " << Info.max_lifetime << "\n";
76+
<< "MaxLifetime: " << Info.MaxLifetime << "\n";
7777
OS << " "
78-
<< "AllocCpuId: " << Info.alloc_cpu_id << "\n";
78+
<< "AllocCpuId: " << Info.AllocCpuId << "\n";
7979
OS << " "
80-
<< "DeallocCpuId: " << Info.dealloc_cpu_id << "\n";
80+
<< "DeallocCpuId: " << Info.DeallocCpuId << "\n";
8181
OS << " "
82-
<< "NumMigratedCpu: " << Info.num_migrated_cpu << "\n";
82+
<< "NumMigratedCpu: " << Info.NumMigratedCpu << "\n";
8383
OS << " "
84-
<< "NumLifetimeOverlaps: " << Info.num_lifetime_overlaps << "\n";
84+
<< "NumLifetimeOverlaps: " << Info.NumLifetimeOverlaps << "\n";
8585
OS << " "
86-
<< "NumSameAllocCpu: " << Info.num_same_alloc_cpu << "\n";
86+
<< "NumSameAllocCpu: " << Info.NumSameAllocCpu << "\n";
8787
OS << " "
88-
<< "NumSameDeallocCpu: " << Info.num_same_dealloc_cpu << "\n";
88+
<< "NumSameDeallocCpu: " << Info.NumSameDeallocCpu << "\n";
8989
}
9090
};
9191

0 commit comments

Comments
 (0)