1 #ifndef MEMPROF_DATA_INC
2 #define MEMPROF_DATA_INC
3 /*===-- MemProfData.inc - MemProf profiling runtime structures -*- C++ -*-=== *\
5 |* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6 |* See https://llvm.org/LICENSE.txt for license information.
7 |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
9 \*===----------------------------------------------------------------------===*/
11 * This is the main file that defines all the data structure, signature,
12 * constant literals that are shared across profiling runtime library,
13 * and host tools (reader/writer).
15 * This file has two identical copies. The primary copy lives in LLVM and
16 * the other one sits in compiler-rt/include/profile directory. To make changes
17 * in this file, first modify the primary copy and copy it over to compiler-rt.
18 * Testing of any change in this file can start only after the two copies are
21 \*===----------------------------------------------------------------------===*/
25 #define PACKED(...) __pragma(pack(push,1)) __VA_ARGS__ __pragma(pack(pop))
27 #define PACKED(...) __VA_ARGS__ __attribute__((__packed__))
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)
35 // The version number of the raw binary format.
36 #define MEMPROF_RAW_VERSION 3ULL
38 #define MEMPROF_BUILDID_MAX_SIZE 32ULL
42 // A struct describing the header used for the raw binary memprof profile format.
43 PACKED(struct Header {
47 uint64_t SegmentOffset;
52 // A struct describing the information necessary to describe a /proc/maps
53 // segment entry for a particular binary/library identified by its build id.
54 PACKED(struct SegmentEntry {
59 uint8_t BuildId[MEMPROF_BUILDID_MAX_SIZE] = {0};
61 // This constructor is only used in tests so don't set the BuildId.
62 SegmentEntry(uint64_t S, uint64_t E, uint64_t O)
63 : Start(S), End(E), Offset(O), BuildIdSize(0) {}
65 SegmentEntry(const SegmentEntry& S) {
69 BuildIdSize = S.BuildIdSize;
70 memcpy(BuildId, S.BuildId, S.BuildIdSize);
73 SegmentEntry& operator=(const SegmentEntry& S) {
77 BuildIdSize = S.BuildIdSize;
78 memcpy(BuildId, S.BuildId, S.BuildIdSize);
82 bool operator==(const SegmentEntry& S) const {
83 return Start == S.Start && End == S.End && Offset == S.Offset &&
84 BuildIdSize == S.BuildIdSize &&
85 memcmp(BuildId, S.BuildId, S.BuildIdSize) == 0;
89 // Packed struct definition for MSVC. We can't use the PACKED macro defined in
90 // MemProfData.inc since it would mean we are embedding a directive (the
91 // #include for MIBEntryDef) into the macros which is undefined behaviour.
93 __pragma(pack(push,1))
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.
102 #define MIBEntryDef(NameTag, Name, Type) Type Name;
103 #include "MIBEntryDef.inc"
106 bool operator==(const MemInfoBlock& Other) const {
108 #define MIBEntryDef(NameTag, Name, Type) \
109 IsEqual = (IsEqual && Name == Other.Name);
110 #include "MIBEntryDef.inc"
116 #define MIBEntryDef(NameTag, Name, Type) Name = Type();
117 #include "MIBEntryDef.inc"
121 MemInfoBlock(uint32_t Size, uint64_t AccessCount, uint32_t AllocTs,
122 uint32_t DeallocTs, uint32_t AllocCpu, uint32_t DeallocCpu)
125 TotalAccessCount = AccessCount;
126 MinAccessCount = AccessCount;
127 MaxAccessCount = AccessCount;
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
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;
154 void Merge(const MemInfoBlock &newMIB) {
155 AllocCount += newMIB.AllocCount;
157 TotalAccessCount += newMIB.TotalAccessCount;
158 MinAccessCount = newMIB.MinAccessCount < MinAccessCount ? newMIB.MinAccessCount : MinAccessCount;
159 MaxAccessCount = newMIB.MaxAccessCount > MaxAccessCount ? newMIB.MaxAccessCount : MaxAccessCount;
161 TotalSize += newMIB.TotalSize;
162 MinSize = newMIB.MinSize < MinSize ? newMIB.MinSize : MinSize;
163 MaxSize = newMIB.MaxSize > MaxSize ? newMIB.MaxSize : MaxSize;
165 TotalLifetime += newMIB.TotalLifetime;
166 MinLifetime = newMIB.MinLifetime < MinLifetime ? newMIB.MinLifetime : MinLifetime;
167 MaxLifetime = newMIB.MaxLifetime > MaxLifetime ? newMIB.MaxLifetime : MaxLifetime;
169 TotalAccessDensity += newMIB.TotalAccessDensity;
170 MinAccessDensity = newMIB.MinAccessDensity < MinAccessDensity
171 ? newMIB.MinAccessDensity
173 MaxAccessDensity = newMIB.MaxAccessDensity > MaxAccessDensity
174 ? newMIB.MaxAccessDensity
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;
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;
193 NumSameAllocCpu += AllocCpuId == newMIB.AllocCpuId;
194 NumSameDeallocCpu += DeallocCpuId == newMIB.DeallocCpuId;
195 AllocCpuId = newMIB.AllocCpuId;
196 DeallocCpuId = newMIB.DeallocCpuId;
200 } __pragma(pack(pop));
202 } __attribute__((__packed__));
205 } // namespace memprof