MemProfData.inc 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. #ifndef MEMPROF_DATA_INC
  2. #define MEMPROF_DATA_INC
  3. /*===-- MemProfData.inc - MemProf profiling runtime structures -*- C++ -*-=== *\
  4. |*
  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
  8. |*
  9. \*===----------------------------------------------------------------------===*/
  10. /*
  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).
  14. *
  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
  19. * synced up.
  20. *
  21. \*===----------------------------------------------------------------------===*/
  22. #include <string.h>
  23. #ifdef _MSC_VER
  24. #define PACKED(...) __pragma(pack(push,1)) __VA_ARGS__ __pragma(pack(pop))
  25. #else
  26. #define PACKED(...) __VA_ARGS__ __attribute__((__packed__))
  27. #endif
  28. // A 64-bit magic number to uniquely identify the raw binary memprof profile file.
  29. #define MEMPROF_RAW_MAGIC_64 \
  30. ((uint64_t)255 << 56 | (uint64_t)'m' << 48 | (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | \
  31. (uint64_t)'o' << 24 | (uint64_t)'f' << 16 | (uint64_t)'r' << 8 | (uint64_t)129)
  32. // The version number of the raw binary format.
  33. #define MEMPROF_RAW_VERSION 3ULL
  34. #define MEMPROF_BUILDID_MAX_SIZE 32ULL
  35. namespace llvm {
  36. namespace memprof {
  37. // A struct describing the header used for the raw binary memprof profile format.
  38. PACKED(struct Header {
  39. uint64_t Magic;
  40. uint64_t Version;
  41. uint64_t TotalSize;
  42. uint64_t SegmentOffset;
  43. uint64_t MIBOffset;
  44. uint64_t StackOffset;
  45. });
  46. // A struct describing the information necessary to describe a /proc/maps
  47. // segment entry for a particular binary/library identified by its build id.
  48. PACKED(struct SegmentEntry {
  49. uint64_t Start;
  50. uint64_t End;
  51. uint64_t Offset;
  52. uint64_t BuildIdSize;
  53. uint8_t BuildId[MEMPROF_BUILDID_MAX_SIZE] = {0};
  54. // This constructor is only used in tests so don't set the BuildId.
  55. SegmentEntry(uint64_t S, uint64_t E, uint64_t O)
  56. : Start(S), End(E), Offset(O), BuildIdSize(0) {}
  57. SegmentEntry(const SegmentEntry& S) {
  58. Start = S.Start;
  59. End = S.End;
  60. Offset = S.Offset;
  61. BuildIdSize = S.BuildIdSize;
  62. memcpy(BuildId, S.BuildId, S.BuildIdSize);
  63. }
  64. SegmentEntry& operator=(const SegmentEntry& S) {
  65. Start = S.Start;
  66. End = S.End;
  67. Offset = S.Offset;
  68. BuildIdSize = S.BuildIdSize;
  69. memcpy(BuildId, S.BuildId, S.BuildIdSize);
  70. return *this;
  71. }
  72. bool operator==(const SegmentEntry& S) const {
  73. return Start == S.Start && End == S.End && Offset == S.Offset &&
  74. BuildIdSize == S.BuildIdSize &&
  75. memcmp(BuildId, S.BuildId, S.BuildIdSize) == 0;
  76. }
  77. });
  78. // Packed struct definition for MSVC. We can't use the PACKED macro defined in
  79. // MemProfData.inc since it would mean we are embedding a directive (the
  80. // #include for MIBEntryDef) into the macros which is undefined behaviour.
  81. #ifdef _MSC_VER
  82. __pragma(pack(push,1))
  83. #endif
  84. // A struct representing the heap allocation characteristics of a particular
  85. // runtime context. This struct is shared between the compiler-rt runtime and
  86. // the raw profile reader. The indexed format uses a separate, self-describing
  87. // backwards compatible format.
  88. struct MemInfoBlock{
  89. #define MIBEntryDef(NameTag, Name, Type) Type Name;
  90. #include "MIBEntryDef.inc"
  91. #undef MIBEntryDef
  92. bool operator==(const MemInfoBlock& Other) const {
  93. bool IsEqual = true;
  94. #define MIBEntryDef(NameTag, Name, Type) \
  95. IsEqual = (IsEqual && Name == Other.Name);
  96. #include "MIBEntryDef.inc"
  97. #undef MIBEntryDef
  98. return IsEqual;
  99. }
  100. MemInfoBlock() {
  101. #define MIBEntryDef(NameTag, Name, Type) Name = Type();
  102. #include "MIBEntryDef.inc"
  103. #undef MIBEntryDef
  104. }
  105. MemInfoBlock(uint32_t Size, uint64_t AccessCount, uint32_t AllocTs,
  106. uint32_t DeallocTs, uint32_t AllocCpu, uint32_t DeallocCpu)
  107. : MemInfoBlock() {
  108. AllocCount = 1U;
  109. TotalAccessCount = AccessCount;
  110. MinAccessCount = AccessCount;
  111. MaxAccessCount = AccessCount;
  112. TotalSize = Size;
  113. MinSize = Size;
  114. MaxSize = Size;
  115. AllocTimestamp = AllocTs;
  116. DeallocTimestamp = DeallocTs;
  117. TotalLifetime = DeallocTimestamp - AllocTimestamp;
  118. MinLifetime = TotalLifetime;
  119. MaxLifetime = TotalLifetime;
  120. // Access density is accesses per byte. Multiply by 100 to include the
  121. // fractional part.
  122. TotalAccessDensity = AccessCount * 100 / Size;
  123. MinAccessDensity = TotalAccessDensity;
  124. MaxAccessDensity = TotalAccessDensity;
  125. // Lifetime access density is the access density per second of lifetime.
  126. // Multiply by 1000 to convert denominator lifetime to seconds (using a
  127. // minimum lifetime of 1ms to avoid divide by 0. Do the multiplication first
  128. // to reduce truncations to 0.
  129. TotalLifetimeAccessDensity =
  130. TotalAccessDensity * 1000 / (TotalLifetime ? TotalLifetime : 1);
  131. MinLifetimeAccessDensity = TotalLifetimeAccessDensity;
  132. MaxLifetimeAccessDensity = TotalLifetimeAccessDensity;
  133. AllocCpuId = AllocCpu;
  134. DeallocCpuId = DeallocCpu;
  135. NumMigratedCpu = AllocCpuId != DeallocCpuId;
  136. }
  137. void Merge(const MemInfoBlock &newMIB) {
  138. AllocCount += newMIB.AllocCount;
  139. TotalAccessCount += newMIB.TotalAccessCount;
  140. MinAccessCount = newMIB.MinAccessCount < MinAccessCount ? newMIB.MinAccessCount : MinAccessCount;
  141. MaxAccessCount = newMIB.MaxAccessCount > MaxAccessCount ? newMIB.MaxAccessCount : MaxAccessCount;
  142. TotalSize += newMIB.TotalSize;
  143. MinSize = newMIB.MinSize < MinSize ? newMIB.MinSize : MinSize;
  144. MaxSize = newMIB.MaxSize > MaxSize ? newMIB.MaxSize : MaxSize;
  145. TotalLifetime += newMIB.TotalLifetime;
  146. MinLifetime = newMIB.MinLifetime < MinLifetime ? newMIB.MinLifetime : MinLifetime;
  147. MaxLifetime = newMIB.MaxLifetime > MaxLifetime ? newMIB.MaxLifetime : MaxLifetime;
  148. TotalAccessDensity += newMIB.TotalAccessDensity;
  149. MinAccessDensity = newMIB.MinAccessDensity < MinAccessDensity
  150. ? newMIB.MinAccessDensity
  151. : MinAccessDensity;
  152. MaxAccessDensity = newMIB.MaxAccessDensity > MaxAccessDensity
  153. ? newMIB.MaxAccessDensity
  154. : MaxAccessDensity;
  155. TotalLifetimeAccessDensity += newMIB.TotalLifetimeAccessDensity;
  156. MinLifetimeAccessDensity =
  157. newMIB.MinLifetimeAccessDensity < MinLifetimeAccessDensity
  158. ? newMIB.MinLifetimeAccessDensity
  159. : MinLifetimeAccessDensity;
  160. MaxLifetimeAccessDensity =
  161. newMIB.MaxLifetimeAccessDensity > MaxLifetimeAccessDensity
  162. ? newMIB.MaxLifetimeAccessDensity
  163. : MaxLifetimeAccessDensity;
  164. // We know newMIB was deallocated later, so just need to check if it was
  165. // allocated before last one deallocated.
  166. NumLifetimeOverlaps += newMIB.AllocTimestamp < DeallocTimestamp;
  167. AllocTimestamp = newMIB.AllocTimestamp;
  168. DeallocTimestamp = newMIB.DeallocTimestamp;
  169. NumSameAllocCpu += AllocCpuId == newMIB.AllocCpuId;
  170. NumSameDeallocCpu += DeallocCpuId == newMIB.DeallocCpuId;
  171. AllocCpuId = newMIB.AllocCpuId;
  172. DeallocCpuId = newMIB.DeallocCpuId;
  173. }
  174. #ifdef _MSC_VER
  175. } __pragma(pack(pop));
  176. #else
  177. } __attribute__((__packed__));
  178. #endif
  179. } // namespace memprof
  180. } // namespace llvm
  181. #endif