Warning, /include/llvm/ProfileData/MemProfData.inc is written in an unsupported language. File is not indexed.
0001 #ifndef MEMPROF_DATA_INC
0002 #define MEMPROF_DATA_INC
0003 /*===-- MemProfData.inc - MemProf profiling runtime structures -*- C++ -*-=== *\
0004 |*
0005 |* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0006 |* See https://llvm.org/LICENSE.txt for license information.
0007 |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0008 |*
0009 \*===----------------------------------------------------------------------===*/
0010 /*
0011 * This is the main file that defines all the data structure, signature,
0012 * constant literals that are shared across profiling runtime library,
0013 * and host tools (reader/writer).
0014 *
0015 * This file has two identical copies. The primary copy lives in LLVM and
0016 * the other one sits in compiler-rt/include/profile directory. To make changes
0017 * in this file, first modify the primary copy and copy it over to compiler-rt.
0018 * Testing of any change in this file can start only after the two copies are
0019 * synced up.
0020 *
0021 \*===----------------------------------------------------------------------===*/
0022 #include <string.h>
0023
0024 #ifdef _MSC_VER
0025 #define PACKED(...) __pragma(pack(push,1)) __VA_ARGS__ __pragma(pack(pop))
0026 #else
0027 #define PACKED(...) __VA_ARGS__ __attribute__((__packed__))
0028 #endif
0029
0030 // A 64-bit magic number to uniquely identify the raw binary memprof profile file.
0031 #define MEMPROF_RAW_MAGIC_64 \
0032 ((uint64_t)255 << 56 | (uint64_t)'m' << 48 | (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | \
0033 (uint64_t)'o' << 24 | (uint64_t)'f' << 16 | (uint64_t)'r' << 8 | (uint64_t)129)
0034
0035 // The version number of the raw binary format.
0036 #define MEMPROF_RAW_VERSION 4ULL
0037
0038 // Currently supported versions.
0039 #define MEMPROF_RAW_SUPPORTED_VERSIONS \
0040 { 3ULL, 4ULL }
0041
0042 #define MEMPROF_V3_MIB_SIZE 132ULL;
0043
0044 #define MEMPROF_BUILDID_MAX_SIZE 32ULL
0045
0046 namespace llvm {
0047 namespace memprof {
0048 // A struct describing the header used for the raw binary memprof profile format.
0049 PACKED(struct Header {
0050 uint64_t Magic;
0051 uint64_t Version;
0052 uint64_t TotalSize;
0053 uint64_t SegmentOffset;
0054 uint64_t MIBOffset;
0055 uint64_t StackOffset;
0056 });
0057
0058 // A struct describing the information necessary to describe a /proc/maps
0059 // segment entry for a particular binary/library identified by its build id.
0060 PACKED(struct SegmentEntry {
0061 uint64_t Start;
0062 uint64_t End;
0063 uint64_t Offset;
0064 uint64_t BuildIdSize;
0065 uint8_t BuildId[MEMPROF_BUILDID_MAX_SIZE] = {0};
0066
0067 // This constructor is only used in tests so don't set the BuildId.
0068 SegmentEntry(uint64_t S, uint64_t E, uint64_t O)
0069 : Start(S), End(E), Offset(O), BuildIdSize(0) {}
0070
0071 SegmentEntry(const SegmentEntry& S) {
0072 Start = S.Start;
0073 End = S.End;
0074 Offset = S.Offset;
0075 BuildIdSize = S.BuildIdSize;
0076 memcpy(BuildId, S.BuildId, S.BuildIdSize);
0077 }
0078
0079 SegmentEntry& operator=(const SegmentEntry& S) {
0080 Start = S.Start;
0081 End = S.End;
0082 Offset = S.Offset;
0083 BuildIdSize = S.BuildIdSize;
0084 memcpy(BuildId, S.BuildId, S.BuildIdSize);
0085 return *this;
0086 }
0087
0088 bool operator==(const SegmentEntry& S) const {
0089 return Start == S.Start && End == S.End && Offset == S.Offset &&
0090 BuildIdSize == S.BuildIdSize &&
0091 memcmp(BuildId, S.BuildId, S.BuildIdSize) == 0;
0092 }
0093 });
0094
0095 // Packed struct definition for MSVC. We can't use the PACKED macro defined in
0096 // MemProfData.inc since it would mean we are embedding a directive (the
0097 // #include for MIBEntryDef) into the macros which is undefined behaviour.
0098 #ifdef _MSC_VER
0099 __pragma(pack(push,1))
0100 #endif
0101
0102 // A struct representing the heap allocation characteristics of a particular
0103 // runtime context. This struct is shared between the compiler-rt runtime and
0104 // the raw profile reader. The indexed format uses a separate, self-describing
0105 // backwards compatible format.
0106 struct MemInfoBlock{
0107
0108 #define MIBEntryDef(NameTag, Name, Type) Type Name;
0109 #include "MIBEntryDef.inc"
0110 #undef MIBEntryDef
0111
0112 bool operator==(const MemInfoBlock& Other) const {
0113 bool IsEqual = true;
0114 #define MIBEntryDef(NameTag, Name, Type) \
0115 IsEqual = (IsEqual && Name == Other.Name);
0116 #include "MIBEntryDef.inc"
0117 #undef MIBEntryDef
0118 return IsEqual;
0119 }
0120
0121 MemInfoBlock() {
0122 #define MIBEntryDef(NameTag, Name, Type) Name = Type();
0123 #include "MIBEntryDef.inc"
0124 #undef MIBEntryDef
0125 }
0126
0127 MemInfoBlock(uint32_t Size, uint64_t AccessCount, uint32_t AllocTs,
0128 uint32_t DeallocTs, uint32_t AllocCpu, uint32_t DeallocCpu,
0129 uintptr_t Histogram, uint32_t HistogramSize)
0130 : MemInfoBlock() {
0131 AllocCount = 1U;
0132 TotalAccessCount = AccessCount;
0133 MinAccessCount = AccessCount;
0134 MaxAccessCount = AccessCount;
0135 TotalSize = Size;
0136 MinSize = Size;
0137 MaxSize = Size;
0138 AllocTimestamp = AllocTs;
0139 DeallocTimestamp = DeallocTs;
0140 TotalLifetime = DeallocTimestamp - AllocTimestamp;
0141 MinLifetime = TotalLifetime;
0142 MaxLifetime = TotalLifetime;
0143 // Access density is accesses per byte. Multiply by 100 to include the
0144 // fractional part.
0145 TotalAccessDensity = AccessCount * 100 / Size;
0146 MinAccessDensity = TotalAccessDensity;
0147 MaxAccessDensity = TotalAccessDensity;
0148 // Lifetime access density is the access density per second of lifetime.
0149 // Multiply by 1000 to convert denominator lifetime to seconds (using a
0150 // minimum lifetime of 1ms to avoid divide by 0. Do the multiplication first
0151 // to reduce truncations to 0.
0152 TotalLifetimeAccessDensity =
0153 TotalAccessDensity * 1000 / (TotalLifetime ? TotalLifetime : 1);
0154 MinLifetimeAccessDensity = TotalLifetimeAccessDensity;
0155 MaxLifetimeAccessDensity = TotalLifetimeAccessDensity;
0156 AllocCpuId = AllocCpu;
0157 DeallocCpuId = DeallocCpu;
0158 NumMigratedCpu = AllocCpuId != DeallocCpuId;
0159 AccessHistogramSize = HistogramSize;
0160 AccessHistogram = Histogram;
0161 }
0162
0163 void Merge(const MemInfoBlock &newMIB) {
0164 AllocCount += newMIB.AllocCount;
0165
0166 TotalAccessCount += newMIB.TotalAccessCount;
0167 MinAccessCount = newMIB.MinAccessCount < MinAccessCount ? newMIB.MinAccessCount : MinAccessCount;
0168 MaxAccessCount = newMIB.MaxAccessCount > MaxAccessCount ? newMIB.MaxAccessCount : MaxAccessCount;
0169
0170 TotalSize += newMIB.TotalSize;
0171 MinSize = newMIB.MinSize < MinSize ? newMIB.MinSize : MinSize;
0172 MaxSize = newMIB.MaxSize > MaxSize ? newMIB.MaxSize : MaxSize;
0173
0174 TotalLifetime += newMIB.TotalLifetime;
0175 MinLifetime = newMIB.MinLifetime < MinLifetime ? newMIB.MinLifetime : MinLifetime;
0176 MaxLifetime = newMIB.MaxLifetime > MaxLifetime ? newMIB.MaxLifetime : MaxLifetime;
0177
0178 TotalAccessDensity += newMIB.TotalAccessDensity;
0179 MinAccessDensity = newMIB.MinAccessDensity < MinAccessDensity
0180 ? newMIB.MinAccessDensity
0181 : MinAccessDensity;
0182 MaxAccessDensity = newMIB.MaxAccessDensity > MaxAccessDensity
0183 ? newMIB.MaxAccessDensity
0184 : MaxAccessDensity;
0185
0186 TotalLifetimeAccessDensity += newMIB.TotalLifetimeAccessDensity;
0187 MinLifetimeAccessDensity =
0188 newMIB.MinLifetimeAccessDensity < MinLifetimeAccessDensity
0189 ? newMIB.MinLifetimeAccessDensity
0190 : MinLifetimeAccessDensity;
0191 MaxLifetimeAccessDensity =
0192 newMIB.MaxLifetimeAccessDensity > MaxLifetimeAccessDensity
0193 ? newMIB.MaxLifetimeAccessDensity
0194 : MaxLifetimeAccessDensity;
0195
0196 // We know newMIB was deallocated later, so just need to check if it was
0197 // allocated before last one deallocated.
0198 NumLifetimeOverlaps += newMIB.AllocTimestamp < DeallocTimestamp;
0199 AllocTimestamp = newMIB.AllocTimestamp;
0200 DeallocTimestamp = newMIB.DeallocTimestamp;
0201
0202 NumSameAllocCpu += AllocCpuId == newMIB.AllocCpuId;
0203 NumSameDeallocCpu += DeallocCpuId == newMIB.DeallocCpuId;
0204 AllocCpuId = newMIB.AllocCpuId;
0205 DeallocCpuId = newMIB.DeallocCpuId;
0206
0207 // For merging histograms, we always keep the longer histogram, and add
0208 // values of shorter histogram to larger one.
0209 uintptr_t ShorterHistogram;
0210 uint32_t ShorterHistogramSize;
0211 if (newMIB.AccessHistogramSize > AccessHistogramSize) {
0212 ShorterHistogram = AccessHistogram;
0213 ShorterHistogramSize = AccessHistogramSize;
0214 // Swap histogram of current to larger histogram
0215 AccessHistogram = newMIB.AccessHistogram;
0216 AccessHistogramSize = newMIB.AccessHistogramSize;
0217 } else {
0218 ShorterHistogram = newMIB.AccessHistogram;
0219 ShorterHistogramSize = newMIB.AccessHistogramSize;
0220 }
0221 for (size_t i = 0; i < ShorterHistogramSize; ++i) {
0222 ((uint64_t *)AccessHistogram)[i] += ((uint64_t *)ShorterHistogram)[i];
0223 }
0224 }
0225
0226 #ifdef _MSC_VER
0227 } __pragma(pack(pop));
0228 #else
0229 } __attribute__((__packed__));
0230 #endif
0231
0232 } // namespace memprof
0233 } // namespace llvm
0234
0235 #endif