Skip to content

Commit

Permalink
[MC][NFC] Use vector for GUIDProbeFunctionMap
Browse files Browse the repository at this point in the history
Replace unordered_map with a vector. Pre-parse the section to statically
allocate storage. Use BumpPtrAllocator for FuncName strings, keep
StringRef in FuncDesc.

Reduces peak RSS of pseudo probe parsing from 9.08 GiB to 8.89 GiB as
part of perf2bolt with a large binary.

Test Plan:
```
bin/llvm-lit -sv test/tools/llvm-profgen
```

Reviewers: wlei-llvm, rafaelauler, dcci, maksfb, ayermolo

Reviewed By: wlei-llvm

Pull Request: llvm#102905
  • Loading branch information
aaupov committed Aug 26, 2024
1 parent ee09f7d commit a79cf02
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 25 deletions.
3 changes: 2 additions & 1 deletion bolt/lib/Rewrite/PseudoProbeRewriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@ void PseudoProbeRewriter::parsePseudoProbe() {
ProbeDecoder.printProbesForAllAddresses(outs());
}

for (const auto &[GUID, FuncDesc] : ProbeDecoder.getGUID2FuncDescMap()) {
for (const auto &FuncDesc : ProbeDecoder.getGUID2FuncDescMap()) {
uint64_t GUID = FuncDesc.FuncGUID;
if (!FuncStartAddrs.contains(GUID))
continue;
BinaryFunction *BF = BC.getBinaryFunctionAtAddress(FuncStartAddrs[GUID]);
Expand Down
19 changes: 16 additions & 3 deletions llvm/include/llvm/MC/MCPseudoProbe.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
#include "llvm/IR/PseudoProbe.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/ErrorOr.h"
#include <functional>
#include <memory>
Expand All @@ -86,7 +87,7 @@ enum class MCPseudoProbeFlag {
struct MCPseudoProbeFuncDesc {
uint64_t FuncGUID = 0;
uint64_t FuncHash = 0;
std::string FuncName;
StringRef FuncName;

MCPseudoProbeFuncDesc(uint64_t GUID, uint64_t Hash, StringRef Name)
: FuncGUID(GUID), FuncHash(Hash), FuncName(Name){};
Expand All @@ -100,8 +101,18 @@ class MCDecodedPseudoProbe;
using InlineSite = std::tuple<uint64_t, uint32_t>;
using MCPseudoProbeInlineStack = SmallVector<InlineSite, 8>;
// GUID to PseudoProbeFuncDesc map
using GUIDProbeFunctionMap =
std::unordered_map<uint64_t, MCPseudoProbeFuncDesc>;
class GUIDProbeFunctionMap : public std::vector<MCPseudoProbeFuncDesc> {
public:
auto find(uint64_t GUID) const {
auto CompareDesc = [](const MCPseudoProbeFuncDesc &Desc, uint64_t GUID) {
return Desc.FuncGUID < GUID;
};
auto It = llvm::lower_bound(*this, GUID, CompareDesc);
if (It->FuncGUID != GUID)
return end();
return It;
}
};

class MCDecodedPseudoProbeInlineTree;

Expand Down Expand Up @@ -389,6 +400,8 @@ class MCPseudoProbeDecoder {
// GUID to PseudoProbeFuncDesc map.
GUIDProbeFunctionMap GUID2FuncDescMap;

BumpPtrAllocator FuncNameAllocator;

// Address to probes map.
AddressProbesMap Address2ProbesMap;

Expand Down
52 changes: 31 additions & 21 deletions llvm/lib/MC/MCPseudoProbe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ static StringRef getProbeFNameForGUID(const GUIDProbeFunctionMap &GUID2FuncMAP,
auto It = GUID2FuncMAP.find(GUID);
assert(It != GUID2FuncMAP.end() &&
"Probe function must exist for a valid GUID");
return It->second.FuncName;
return It->FuncName;
}

void MCPseudoProbeFuncDesc::print(raw_ostream &OS) {
Expand Down Expand Up @@ -390,32 +390,46 @@ bool MCPseudoProbeDecoder::buildGUID2FuncDescMap(const uint8_t *Start,
Data = Start;
End = Data + Size;

uint32_t FuncDescCount = 0;
while (Data < End) {
auto ErrorOrGUID = readUnencodedNumber<uint64_t>();
if (!ErrorOrGUID)
// GUID
if (!readUnencodedNumber<uint64_t>())
return false;

auto ErrorOrHash = readUnencodedNumber<uint64_t>();
if (!ErrorOrHash)
// Hash
if (!readUnencodedNumber<uint64_t>())
return false;

auto ErrorOrNameSize = readUnsignedNumber<uint32_t>();
if (!ErrorOrNameSize)
return false;
uint32_t NameSize = std::move(*ErrorOrNameSize);

auto ErrorOrName = readString(NameSize);
if (!ErrorOrName)
// Function name
if (!readString(*ErrorOrNameSize))
return false;
++FuncDescCount;
}
assert(Data == End && "Have unprocessed data in pseudo_probe_desc section");
GUID2FuncDescMap.reserve(FuncDescCount);

uint64_t GUID = std::move(*ErrorOrGUID);
uint64_t Hash = std::move(*ErrorOrHash);
StringRef Name = std::move(*ErrorOrName);
Data = Start;
End = Data + Size;
while (Data < End) {
uint64_t GUID =
cantFail(errorOrToExpected(readUnencodedNumber<uint64_t>()));
uint64_t Hash =
cantFail(errorOrToExpected(readUnencodedNumber<uint64_t>()));
uint32_t NameSize =
cantFail(errorOrToExpected(readUnsignedNumber<uint32_t>()));
StringRef Name = cantFail(errorOrToExpected(readString(NameSize)));

// Initialize PseudoProbeFuncDesc and populate it into GUID2FuncDescMap
GUID2FuncDescMap.emplace(GUID, MCPseudoProbeFuncDesc(GUID, Hash, Name));
GUID2FuncDescMap.emplace_back(GUID, Hash, Name.copy(FuncNameAllocator));
}
assert(Data == End && "Have unprocessed data in pseudo_probe_desc section");
assert(GUID2FuncDescMap.size() == FuncDescCount &&
"Mismatching function description count pre- and post-parsing");
llvm::sort(GUID2FuncDescMap, [](const auto &LHS, const auto &RHS) {
return LHS.FuncGUID < RHS.FuncGUID;
});
return true;
}

Expand Down Expand Up @@ -648,12 +662,8 @@ bool MCPseudoProbeDecoder::buildAddress2ProbeMap(

void MCPseudoProbeDecoder::printGUID2FuncDescMap(raw_ostream &OS) {
OS << "Pseudo Probe Desc:\n";
// Make the output deterministic
std::map<uint64_t, MCPseudoProbeFuncDesc> OrderedMap(GUID2FuncDescMap.begin(),
GUID2FuncDescMap.end());
for (auto &I : OrderedMap) {
I.second.print(OS);
}
for (auto &I : GUID2FuncDescMap)
I.print(OS);
}

void MCPseudoProbeDecoder::printProbeForAddress(raw_ostream &OS,
Expand Down Expand Up @@ -705,7 +715,7 @@ const MCPseudoProbeFuncDesc *
MCPseudoProbeDecoder::getFuncDescForGUID(uint64_t GUID) const {
auto It = GUID2FuncDescMap.find(GUID);
assert(It != GUID2FuncDescMap.end() && "Function descriptor doesn't exist");
return &It->second;
return &*It;
}

void MCPseudoProbeDecoder::getInlineContextForProbe(
Expand Down

0 comments on commit a79cf02

Please sign in to comment.