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