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
23// Upper bound on lifetime access density (accesses per byte per lifetime sec)
24// for marking an allocation cold.
25LLVM_ABI cl::opt<float> MemProfLifetimeAccessDensityColdThreshold(
26 "memprof-lifetime-access-density-cold-threshold", cl::init(Val: 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.
33LLVM_ABI cl::opt<unsigned> MemProfAveLifetimeColdThreshold(
34 "memprof-ave-lifetime-cold-threshold", cl::init(Val: 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.
40LLVM_ABI cl::opt<unsigned> MemProfMinAveLifetimeAccessDensityHotThreshold(
41 "memprof-min-ave-lifetime-access-density-hot-threshold", cl::init(Val: 1000),
42 cl::Hidden,
43 cl::desc("The minimum TotalLifetimeAccessDensity / AllocCount for an "
44 "allocation to be considered hot"));
45
46LLVM_ABI cl::opt<bool>
47 MemProfUseHotHints("memprof-use-hot-hints", cl::init(Val: false), cl::Hidden,
48 cl::desc("Enable use of hot hints (only supported for "
49 "unambigously hot allocations)"));
50
51AllocationType 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
73uint64_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(Args: F.Function, Args: F.LineOffset, Args: F.Column);
78 llvm::BLAKE3Result<8> Hash = HashBuilder.final();
79 uint64_t Id;
80 std::memcpy(dest: &Id, src: Hash.data(), n: sizeof(Hash));
81 return Id;
82}
83