xref: /freebsd/contrib/llvm-project/llvm/lib/ProfileData/MemProfCommon.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //=-- MemProfCommon.cpp - MemProf common utilities ---------------=//
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 contains MemProf common utilities.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm/ProfileData/MemProfCommon.h"
14 #include "llvm/ProfileData/MemProf.h"
15 #include "llvm/Support/BLAKE3.h"
16 #include "llvm/Support/CommandLine.h"
17 #include "llvm/Support/Compiler.h"
18 #include "llvm/Support/HashBuilder.h"
19 
20 using namespace llvm;
21 using namespace llvm::memprof;
22 
23 // Upper bound on lifetime access density (accesses per byte per lifetime sec)
24 // for marking an allocation cold.
25 LLVM_ABI cl::opt<float> MemProfLifetimeAccessDensityColdThreshold(
26     "memprof-lifetime-access-density-cold-threshold", cl::init(0.05),
27     cl::Hidden,
28     cl::desc("The threshold the lifetime access density (accesses per byte per "
29              "lifetime sec) must be under to consider an allocation cold"));
30 
31 // Lower bound on lifetime to mark an allocation cold (in addition to accesses
32 // per byte per sec above). This is to avoid pessimizing short lived objects.
33 LLVM_ABI cl::opt<unsigned> MemProfAveLifetimeColdThreshold(
34     "memprof-ave-lifetime-cold-threshold", cl::init(200), cl::Hidden,
35     cl::desc("The average lifetime (s) for an allocation to be considered "
36              "cold"));
37 
38 // Lower bound on average lifetime accesses density (total life time access
39 // density / alloc count) for marking an allocation hot.
40 LLVM_ABI cl::opt<unsigned> MemProfMinAveLifetimeAccessDensityHotThreshold(
41     "memprof-min-ave-lifetime-access-density-hot-threshold", cl::init(1000),
42     cl::Hidden,
43     cl::desc("The minimum TotalLifetimeAccessDensity / AllocCount for an "
44              "allocation to be considered hot"));
45 
46 LLVM_ABI cl::opt<bool>
47     MemProfUseHotHints("memprof-use-hot-hints", cl::init(false), cl::Hidden,
48                        cl::desc("Enable use of hot hints (only supported for "
49                                 "unambigously hot allocations)"));
50 
getAllocType(uint64_t TotalLifetimeAccessDensity,uint64_t AllocCount,uint64_t TotalLifetime)51 AllocationType llvm::memprof::getAllocType(uint64_t TotalLifetimeAccessDensity,
52                                            uint64_t AllocCount,
53                                            uint64_t TotalLifetime) {
54   // The access densities are multiplied by 100 to hold 2 decimal places of
55   // precision, so need to divide by 100.
56   if (((float)TotalLifetimeAccessDensity) / AllocCount / 100 <
57           MemProfLifetimeAccessDensityColdThreshold
58       // Lifetime is expected to be in ms, so convert the threshold to ms.
59       && ((float)TotalLifetime) / AllocCount >=
60              MemProfAveLifetimeColdThreshold * 1000)
61     return AllocationType::Cold;
62 
63   // The access densities are multiplied by 100 to hold 2 decimal places of
64   // precision, so need to divide by 100.
65   if (MemProfUseHotHints &&
66       ((float)TotalLifetimeAccessDensity) / AllocCount / 100 >
67           MemProfMinAveLifetimeAccessDensityHotThreshold)
68     return AllocationType::Hot;
69 
70   return AllocationType::NotCold;
71 }
72 
computeFullStackId(ArrayRef<Frame> CallStack)73 uint64_t llvm::memprof::computeFullStackId(ArrayRef<Frame> CallStack) {
74   llvm::HashBuilder<llvm::TruncatedBLAKE3<8>, llvm::endianness::little>
75       HashBuilder;
76   for (auto &F : CallStack)
77     HashBuilder.add(F.Function, F.LineOffset, F.Column);
78   llvm::BLAKE3Result<8> Hash = HashBuilder.final();
79   uint64_t Id;
80   std::memcpy(&Id, Hash.data(), sizeof(Hash));
81   return Id;
82 }
83