| //=-- MemProfCommon.cpp - MemProf common utilities ---------------=// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // This file contains MemProf common utilities. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/ProfileData/MemProfCommon.h" | |
| #include "llvm/ProfileData/MemProf.h" | |
| #include "llvm/Support/BLAKE3.h" | |
| #include "llvm/Support/CommandLine.h" | |
| #include "llvm/Support/Compiler.h" | |
| #include "llvm/Support/HashBuilder.h" | |
| using namespace llvm; | |
| using namespace llvm::memprof; | |
| namespace llvm { | |
| // Upper bound on lifetime access density (accesses per byte per lifetime sec) | |
| // for marking an allocation cold. | |
| LLVM_ABI cl::opt<float> MemProfLifetimeAccessDensityColdThreshold( | |
| "memprof-lifetime-access-density-cold-threshold", cl::init(0.05), | |
| cl::Hidden, | |
| cl::desc("The threshold the lifetime access density (accesses per byte per " | |
| "lifetime sec) must be under to consider an allocation cold")); | |
| // Lower bound on lifetime to mark an allocation cold (in addition to accesses | |
| // per byte per sec above). This is to avoid pessimizing short lived objects. | |
| LLVM_ABI cl::opt<unsigned> MemProfAveLifetimeColdThreshold( | |
| "memprof-ave-lifetime-cold-threshold", cl::init(200), cl::Hidden, | |
| cl::desc("The average lifetime (s) for an allocation to be considered " | |
| "cold")); | |
| // Lower bound on average lifetime accesses density (total life time access | |
| // density / alloc count) for marking an allocation hot. | |
| LLVM_ABI cl::opt<unsigned> MemProfMinAveLifetimeAccessDensityHotThreshold( | |
| "memprof-min-ave-lifetime-access-density-hot-threshold", cl::init(1000), | |
| cl::Hidden, | |
| cl::desc("The minimum TotalLifetimeAccessDensity / AllocCount for an " | |
| "allocation to be considered hot")); | |
| LLVM_ABI cl::opt<bool> | |
| MemProfUseHotHints("memprof-use-hot-hints", cl::init(false), cl::Hidden, | |
| cl::desc("Enable use of hot hints (only supported for " | |
| "unambigously hot allocations)")); | |
| } // end namespace llvm | |
| AllocationType llvm::memprof::getAllocType(uint64_t TotalLifetimeAccessDensity, | |
| uint64_t AllocCount, | |
| uint64_t TotalLifetime) { | |
| // The access densities are multiplied by 100 to hold 2 decimal places of | |
| // precision, so need to divide by 100. | |
| if (((float)TotalLifetimeAccessDensity) / AllocCount / 100 < | |
| MemProfLifetimeAccessDensityColdThreshold | |
| // Lifetime is expected to be in ms, so convert the threshold to ms. | |
| && ((float)TotalLifetime) / AllocCount >= | |
| MemProfAveLifetimeColdThreshold * 1000) | |
| return AllocationType::Cold; | |
| // The access densities are multiplied by 100 to hold 2 decimal places of | |
| // precision, so need to divide by 100. | |
| if (MemProfUseHotHints && | |
| ((float)TotalLifetimeAccessDensity) / AllocCount / 100 > | |
| MemProfMinAveLifetimeAccessDensityHotThreshold) | |
| return AllocationType::Hot; | |
| return AllocationType::NotCold; | |
| } | |
| uint64_t llvm::memprof::computeFullStackId(ArrayRef<Frame> CallStack) { | |
| llvm::HashBuilder<llvm::TruncatedBLAKE3<8>, llvm::endianness::little> | |
| HashBuilder; | |
| for (auto &F : CallStack) | |
| HashBuilder.add(F.Function, F.LineOffset, F.Column); | |
| llvm::BLAKE3Result<8> Hash = HashBuilder.final(); | |
| uint64_t Id; | |
| std::memcpy(&Id, Hash.data(), sizeof(Hash)); | |
| return Id; | |
| } |