22
22
#include < string.h>
23
23
24
24
#ifdef _MSC_VER
25
- #define PACKED (...) __pragma(pack(push,1 )) __VA_ARGS__ __pragma (pack(pop))
25
+ #define PACKED (...) __pragma(pack(push, 1 )) __VA_ARGS__ __pragma (pack(pop))
26
26
#else
27
27
#define PACKED (...) __VA_ARGS__ __attribute__ ((__packed__))
28
28
#endif
29
29
30
- // A 64-bit magic number to uniquely identify the raw binary memprof profile file.
31
- #define MEMPROF_RAW_MAGIC_64 \
32
- ((uint64_t )255 << 56 | (uint64_t )' m' << 48 | (uint64_t )' p' << 40 | (uint64_t )' r' << 32 | \
33
- (uint64_t )' o' << 24 | (uint64_t )' f' << 16 | (uint64_t )' r' << 8 | (uint64_t )129 )
30
+ // A 64-bit magic number to uniquely identify the raw binary memprof profile
31
+ // file.
32
+ #define MEMPROF_RAW_MAGIC_64 \
33
+ ((uint64_t )255 << 56 | (uint64_t )' m' << 48 | (uint64_t )' p' << 40 | \
34
+ (uint64_t )' r' << 32 | (uint64_t )' o' << 24 | (uint64_t )' f' << 16 | \
35
+ (uint64_t )' r' << 8 | (uint64_t )129 )
34
36
35
37
// The version number of the raw binary format.
36
- #define MEMPROF_RAW_VERSION 3ULL
38
+ #define MEMPROF_RAW_VERSION 4ULL
37
39
38
40
#define MEMPROF_BUILDID_MAX_SIZE 32ULL
39
41
40
42
namespace llvm {
41
43
namespace memprof {
42
- // A struct describing the header used for the raw binary memprof profile format.
44
+ // A struct describing the header used for the raw binary memprof profile
45
+ // format.
43
46
PACKED (struct Header {
44
47
uint64_t Magic;
45
48
uint64_t Version;
@@ -62,15 +65,15 @@ PACKED(struct SegmentEntry {
62
65
SegmentEntry (uint64_t S, uint64_t E, uint64_t O)
63
66
: Start(S), End(E), Offset(O), BuildIdSize(0 ) {}
64
67
65
- SegmentEntry (const SegmentEntry& S) {
68
+ SegmentEntry (const SegmentEntry & S) {
66
69
Start = S.Start ;
67
70
End = S.End ;
68
71
Offset = S.Offset ;
69
72
BuildIdSize = S.BuildIdSize ;
70
73
memcpy (BuildId, S.BuildId , S.BuildIdSize );
71
74
}
72
75
73
- SegmentEntry& operator =(const SegmentEntry& S) {
76
+ SegmentEntry & operator =(const SegmentEntry & S) {
74
77
Start = S.Start ;
75
78
End = S.End ;
76
79
Offset = S.Offset ;
@@ -79,7 +82,7 @@ PACKED(struct SegmentEntry {
79
82
return *this ;
80
83
}
81
84
82
- bool operator ==(const SegmentEntry& S) const {
85
+ bool operator ==(const SegmentEntry & S) const {
83
86
return Start == S.Start && End == S.End && Offset == S.Offset &&
84
87
BuildIdSize == S.BuildIdSize &&
85
88
memcmp (BuildId, S.BuildId , S.BuildIdSize ) == 0 ;
@@ -90,111 +93,143 @@ PACKED(struct SegmentEntry {
90
93
// MemProfData.inc since it would mean we are embedding a directive (the
91
94
// #include for MIBEntryDef) into the macros which is undefined behaviour.
92
95
#ifdef _MSC_VER
93
- __pragma (pack(push,1 ))
96
+ __pragma (pack(push, 1 ))
94
97
#endif
95
98
96
- // A struct representing the heap allocation characteristics of a particular
97
- // runtime context. This struct is shared between the compiler-rt runtime and
98
- // the raw profile reader. The indexed format uses a separate, self-describing
99
- // backwards compatible format.
100
- struct MemInfoBlock {
99
+ // A struct representing the heap allocation characteristics of a particular
100
+ // runtime context. This struct is shared between the compiler-rt runtime
101
+ // and the raw profile reader. The indexed format uses a separate,
102
+ // self-describing backwards compatible format.
103
+ struct MemInfoBlock {
101
104
102
105
#define MIBEntryDef (NameTag, Name, Type ) Type Name;
103
106
#include " MIBEntryDef.inc"
104
107
#undef MIBEntryDef
105
108
106
- bool operator ==(const MemInfoBlock& Other) const {
107
- bool IsEqual = true ;
108
- #define MIBEntryDef (NameTag, Name, Type ) \
109
+ bool operator ==(const MemInfoBlock & Other) const {
110
+ bool IsEqual = true ;
111
+ #define MIBEntryDef (NameTag, Name, Type ) \
109
112
IsEqual = (IsEqual && Name == Other.Name );
110
113
#include " MIBEntryDef.inc"
111
114
#undef MIBEntryDef
112
- return IsEqual;
113
- }
115
+ return IsEqual;
116
+ }
114
117
115
- MemInfoBlock () {
118
+ MemInfoBlock () {
116
119
#define MIBEntryDef (NameTag, Name, Type ) Name = Type();
117
120
#include " MIBEntryDef.inc"
118
121
#undef MIBEntryDef
119
- }
120
-
121
- MemInfoBlock (uint32_t Size, uint64_t AccessCount, uint32_t AllocTs,
122
- uint32_t DeallocTs, uint32_t AllocCpu, uint32_t DeallocCpu)
123
- : MemInfoBlock() {
124
- AllocCount = 1U ;
125
- TotalAccessCount = AccessCount;
126
- MinAccessCount = AccessCount;
127
- MaxAccessCount = AccessCount;
128
- TotalSize = Size;
129
- MinSize = Size;
130
- MaxSize = Size;
131
- AllocTimestamp = AllocTs;
132
- DeallocTimestamp = DeallocTs;
133
- TotalLifetime = DeallocTimestamp - AllocTimestamp;
134
- MinLifetime = TotalLifetime;
135
- MaxLifetime = TotalLifetime;
136
- // Access density is accesses per byte. Multiply by 100 to include the
137
- // fractional part.
138
- TotalAccessDensity = AccessCount * 100 / Size;
139
- MinAccessDensity = TotalAccessDensity;
140
- MaxAccessDensity = TotalAccessDensity;
141
- // Lifetime access density is the access density per second of lifetime.
142
- // Multiply by 1000 to convert denominator lifetime to seconds (using a
143
- // minimum lifetime of 1ms to avoid divide by 0. Do the multiplication first
144
- // to reduce truncations to 0.
145
- TotalLifetimeAccessDensity =
146
- TotalAccessDensity * 1000 / (TotalLifetime ? TotalLifetime : 1 );
147
- MinLifetimeAccessDensity = TotalLifetimeAccessDensity;
148
- MaxLifetimeAccessDensity = TotalLifetimeAccessDensity;
149
- AllocCpuId = AllocCpu;
150
- DeallocCpuId = DeallocCpu;
151
- NumMigratedCpu = AllocCpuId != DeallocCpuId;
152
- }
153
-
154
- void Merge (const MemInfoBlock &newMIB) {
155
- AllocCount += newMIB.AllocCount ;
156
-
157
- TotalAccessCount += newMIB.TotalAccessCount ;
158
- MinAccessCount = newMIB.MinAccessCount < MinAccessCount ? newMIB.MinAccessCount : MinAccessCount;
159
- MaxAccessCount = newMIB.MaxAccessCount > MaxAccessCount ? newMIB.MaxAccessCount : MaxAccessCount;
160
-
161
- TotalSize += newMIB.TotalSize ;
162
- MinSize = newMIB.MinSize < MinSize ? newMIB.MinSize : MinSize;
163
- MaxSize = newMIB.MaxSize > MaxSize ? newMIB.MaxSize : MaxSize;
164
-
165
- TotalLifetime += newMIB.TotalLifetime ;
166
- MinLifetime = newMIB.MinLifetime < MinLifetime ? newMIB.MinLifetime : MinLifetime;
167
- MaxLifetime = newMIB.MaxLifetime > MaxLifetime ? newMIB.MaxLifetime : MaxLifetime;
168
-
169
- TotalAccessDensity += newMIB.TotalAccessDensity ;
170
- MinAccessDensity = newMIB.MinAccessDensity < MinAccessDensity
171
- ? newMIB.MinAccessDensity
172
- : MinAccessDensity;
173
- MaxAccessDensity = newMIB.MaxAccessDensity > MaxAccessDensity
174
- ? newMIB.MaxAccessDensity
175
- : MaxAccessDensity;
176
-
177
- TotalLifetimeAccessDensity += newMIB.TotalLifetimeAccessDensity ;
178
- MinLifetimeAccessDensity =
179
- newMIB.MinLifetimeAccessDensity < MinLifetimeAccessDensity
180
- ? newMIB.MinLifetimeAccessDensity
181
- : MinLifetimeAccessDensity;
182
- MaxLifetimeAccessDensity =
183
- newMIB.MaxLifetimeAccessDensity > MaxLifetimeAccessDensity
184
- ? newMIB.MaxLifetimeAccessDensity
185
- : MaxLifetimeAccessDensity;
186
-
187
- // We know newMIB was deallocated later, so just need to check if it was
188
- // allocated before last one deallocated.
189
- NumLifetimeOverlaps += newMIB.AllocTimestamp < DeallocTimestamp;
190
- AllocTimestamp = newMIB.AllocTimestamp ;
191
- DeallocTimestamp = newMIB.DeallocTimestamp ;
192
-
193
- NumSameAllocCpu += AllocCpuId == newMIB.AllocCpuId ;
194
- NumSameDeallocCpu += DeallocCpuId == newMIB.DeallocCpuId ;
195
- AllocCpuId = newMIB.AllocCpuId ;
196
- DeallocCpuId = newMIB.DeallocCpuId ;
197
- }
122
+ }
123
+
124
+ MemInfoBlock (uint32_t Size, uint64_t AccessCount, uint32_t AllocTs,
125
+ uint32_t DeallocTs, uint32_t AllocCpu, uint32_t DeallocCpu,
126
+ uintptr_t Histogram, uint32_t HistogramSize)
127
+ : MemInfoBlock() {
128
+ AllocCount = 1U ;
129
+ TotalAccessCount = AccessCount;
130
+ MinAccessCount = AccessCount;
131
+ MaxAccessCount = AccessCount;
132
+ TotalSize = Size;
133
+ MinSize = Size;
134
+ MaxSize = Size;
135
+ AllocTimestamp = AllocTs;
136
+ DeallocTimestamp = DeallocTs;
137
+ TotalLifetime = DeallocTimestamp - AllocTimestamp;
138
+ MinLifetime = TotalLifetime;
139
+ MaxLifetime = TotalLifetime;
140
+ // Access density is accesses per byte. Multiply by 100 to include the
141
+ // fractional part.
142
+ TotalAccessDensity = AccessCount * 100 / Size;
143
+ MinAccessDensity = TotalAccessDensity;
144
+ MaxAccessDensity = TotalAccessDensity;
145
+ // Lifetime access density is the access density per second of lifetime.
146
+ // Multiply by 1000 to convert denominator lifetime to seconds (using a
147
+ // minimum lifetime of 1ms to avoid divide by 0. Do the multiplication first
148
+ // to reduce truncations to 0.
149
+ TotalLifetimeAccessDensity =
150
+ TotalAccessDensity * 1000 / (TotalLifetime ? TotalLifetime : 1 );
151
+ MinLifetimeAccessDensity = TotalLifetimeAccessDensity;
152
+ MaxLifetimeAccessDensity = TotalLifetimeAccessDensity;
153
+ AllocCpuId = AllocCpu;
154
+ DeallocCpuId = DeallocCpu;
155
+ NumMigratedCpu = AllocCpuId != DeallocCpuId;
156
+ // For now we assume HistogramSize is the same as user requested size
157
+ AccessHistogramSize = HistogramSize;
158
+ AccessHistogram = Histogram;
159
+ }
160
+
161
+ // Merge cannot free the AccessHistogram pointer, since we need to free either
162
+ // with InternalFree or free depending on where the allocation is made
163
+ // (runtime or profdata tool). The merge function expects the Histogram
164
+ // pointer with the smaller size to be freed.
165
+ void Merge (const MemInfoBlock &newMIB) {
166
+ AllocCount += newMIB.AllocCount ;
167
+
168
+ TotalAccessCount += newMIB.TotalAccessCount ;
169
+ MinAccessCount = newMIB.MinAccessCount < MinAccessCount
170
+ ? newMIB.MinAccessCount
171
+ : MinAccessCount;
172
+ MaxAccessCount = newMIB.MaxAccessCount > MaxAccessCount
173
+ ? newMIB.MaxAccessCount
174
+ : MaxAccessCount;
175
+
176
+ TotalSize += newMIB.TotalSize ;
177
+ MinSize = newMIB.MinSize < MinSize ? newMIB.MinSize : MinSize;
178
+ MaxSize = newMIB.MaxSize > MaxSize ? newMIB.MaxSize : MaxSize;
179
+
180
+ TotalLifetime += newMIB.TotalLifetime ;
181
+ MinLifetime =
182
+ newMIB.MinLifetime < MinLifetime ? newMIB.MinLifetime : MinLifetime;
183
+ MaxLifetime =
184
+ newMIB.MaxLifetime > MaxLifetime ? newMIB.MaxLifetime : MaxLifetime;
185
+
186
+ TotalAccessDensity += newMIB.TotalAccessDensity ;
187
+ MinAccessDensity = newMIB.MinAccessDensity < MinAccessDensity
188
+ ? newMIB.MinAccessDensity
189
+ : MinAccessDensity;
190
+ MaxAccessDensity = newMIB.MaxAccessDensity > MaxAccessDensity
191
+ ? newMIB.MaxAccessDensity
192
+ : MaxAccessDensity;
193
+
194
+ TotalLifetimeAccessDensity += newMIB.TotalLifetimeAccessDensity ;
195
+ MinLifetimeAccessDensity =
196
+ newMIB.MinLifetimeAccessDensity < MinLifetimeAccessDensity
197
+ ? newMIB.MinLifetimeAccessDensity
198
+ : MinLifetimeAccessDensity;
199
+ MaxLifetimeAccessDensity =
200
+ newMIB.MaxLifetimeAccessDensity > MaxLifetimeAccessDensity
201
+ ? newMIB.MaxLifetimeAccessDensity
202
+ : MaxLifetimeAccessDensity;
203
+
204
+ // We know newMIB was deallocated later, so just need to check if it was
205
+ // allocated before last one deallocated.
206
+ NumLifetimeOverlaps += newMIB.AllocTimestamp < DeallocTimestamp;
207
+ AllocTimestamp = newMIB.AllocTimestamp ;
208
+ DeallocTimestamp = newMIB.DeallocTimestamp ;
209
+
210
+ NumSameAllocCpu += AllocCpuId == newMIB.AllocCpuId ;
211
+ NumSameDeallocCpu += DeallocCpuId == newMIB.DeallocCpuId ;
212
+ AllocCpuId = newMIB.AllocCpuId ;
213
+ DeallocCpuId = newMIB.DeallocCpuId ;
214
+
215
+ // For merging histograms, we always keep the longer histogram, and add
216
+ // values of shorter histogram to larger one.
217
+ uintptr_t ShorterHistogram;
218
+ uint32_t ShorterHistogramSize;
219
+ if (newMIB.AccessHistogramSize > AccessHistogramSize) {
220
+ ShorterHistogram = AccessHistogram;
221
+ ShorterHistogramSize = AccessHistogramSize;
222
+ // Swap histogram of current to larger histogram
223
+ AccessHistogram = newMIB.AccessHistogram ;
224
+ AccessHistogramSize = newMIB.AccessHistogramSize ;
225
+ } else {
226
+ ShorterHistogram = newMIB.AccessHistogram ;
227
+ ShorterHistogramSize = newMIB.AccessHistogramSize ;
228
+ }
229
+ for (size_t i = 0 ; i < ShorterHistogramSize; ++i) {
230
+ ((uint64_t *)AccessHistogram)[i] += ((uint64_t *)ShorterHistogram)[i];
231
+ }
232
+ }
198
233
199
234
#ifdef _MSC_VER
200
235
} __pragma(pack(pop));
@@ -205,4 +240,4 @@ void Merge(const MemInfoBlock &newMIB) {
205
240
} // namespace memprof
206
241
} // namespace llvm
207
242
208
- #endif
243
+ #endif
0 commit comments