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