Skip to content

Commit a79cf02

Browse files
authored
[MC][NFC] Use vector for GUIDProbeFunctionMap
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
1 parent ee09f7d commit a79cf02

File tree

3 files changed

+49
-25
lines changed

3 files changed

+49
-25
lines changed

bolt/lib/Rewrite/PseudoProbeRewriter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,8 @@ void PseudoProbeRewriter::parsePseudoProbe() {
155155
ProbeDecoder.printProbesForAllAddresses(outs());
156156
}
157157

158-
for (const auto &[GUID, FuncDesc] : ProbeDecoder.getGUID2FuncDescMap()) {
158+
for (const auto &FuncDesc : ProbeDecoder.getGUID2FuncDescMap()) {
159+
uint64_t GUID = FuncDesc.FuncGUID;
159160
if (!FuncStartAddrs.contains(GUID))
160161
continue;
161162
BinaryFunction *BF = BC.getBinaryFunctionAtAddress(FuncStartAddrs[GUID]);

llvm/include/llvm/MC/MCPseudoProbe.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
#include "llvm/ADT/StringRef.h"
6262
#include "llvm/ADT/iterator.h"
6363
#include "llvm/IR/PseudoProbe.h"
64+
#include "llvm/Support/Allocator.h"
6465
#include "llvm/Support/ErrorOr.h"
6566
#include <functional>
6667
#include <memory>
@@ -86,7 +87,7 @@ enum class MCPseudoProbeFlag {
8687
struct MCPseudoProbeFuncDesc {
8788
uint64_t FuncGUID = 0;
8889
uint64_t FuncHash = 0;
89-
std::string FuncName;
90+
StringRef FuncName;
9091

9192
MCPseudoProbeFuncDesc(uint64_t GUID, uint64_t Hash, StringRef Name)
9293
: FuncGUID(GUID), FuncHash(Hash), FuncName(Name){};
@@ -100,8 +101,18 @@ class MCDecodedPseudoProbe;
100101
using InlineSite = std::tuple<uint64_t, uint32_t>;
101102
using MCPseudoProbeInlineStack = SmallVector<InlineSite, 8>;
102103
// GUID to PseudoProbeFuncDesc map
103-
using GUIDProbeFunctionMap =
104-
std::unordered_map<uint64_t, MCPseudoProbeFuncDesc>;
104+
class GUIDProbeFunctionMap : public std::vector<MCPseudoProbeFuncDesc> {
105+
public:
106+
auto find(uint64_t GUID) const {
107+
auto CompareDesc = [](const MCPseudoProbeFuncDesc &Desc, uint64_t GUID) {
108+
return Desc.FuncGUID < GUID;
109+
};
110+
auto It = llvm::lower_bound(*this, GUID, CompareDesc);
111+
if (It->FuncGUID != GUID)
112+
return end();
113+
return It;
114+
}
115+
};
105116

106117
class MCDecodedPseudoProbeInlineTree;
107118

@@ -389,6 +400,8 @@ class MCPseudoProbeDecoder {
389400
// GUID to PseudoProbeFuncDesc map.
390401
GUIDProbeFunctionMap GUID2FuncDescMap;
391402

403+
BumpPtrAllocator FuncNameAllocator;
404+
392405
// Address to probes map.
393406
AddressProbesMap Address2ProbesMap;
394407

llvm/lib/MC/MCPseudoProbe.cpp

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ static StringRef getProbeFNameForGUID(const GUIDProbeFunctionMap &GUID2FuncMAP,
274274
auto It = GUID2FuncMAP.find(GUID);
275275
assert(It != GUID2FuncMAP.end() &&
276276
"Probe function must exist for a valid GUID");
277-
return It->second.FuncName;
277+
return It->FuncName;
278278
}
279279

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

393+
uint32_t FuncDescCount = 0;
393394
while (Data < End) {
394-
auto ErrorOrGUID = readUnencodedNumber<uint64_t>();
395-
if (!ErrorOrGUID)
395+
// GUID
396+
if (!readUnencodedNumber<uint64_t>())
396397
return false;
397-
398-
auto ErrorOrHash = readUnencodedNumber<uint64_t>();
399-
if (!ErrorOrHash)
398+
// Hash
399+
if (!readUnencodedNumber<uint64_t>())
400400
return false;
401401

402402
auto ErrorOrNameSize = readUnsignedNumber<uint32_t>();
403403
if (!ErrorOrNameSize)
404404
return false;
405-
uint32_t NameSize = std::move(*ErrorOrNameSize);
406-
407-
auto ErrorOrName = readString(NameSize);
408-
if (!ErrorOrName)
405+
// Function name
406+
if (!readString(*ErrorOrNameSize))
409407
return false;
408+
++FuncDescCount;
409+
}
410+
assert(Data == End && "Have unprocessed data in pseudo_probe_desc section");
411+
GUID2FuncDescMap.reserve(FuncDescCount);
410412

411-
uint64_t GUID = std::move(*ErrorOrGUID);
412-
uint64_t Hash = std::move(*ErrorOrHash);
413-
StringRef Name = std::move(*ErrorOrName);
413+
Data = Start;
414+
End = Data + Size;
415+
while (Data < End) {
416+
uint64_t GUID =
417+
cantFail(errorOrToExpected(readUnencodedNumber<uint64_t>()));
418+
uint64_t Hash =
419+
cantFail(errorOrToExpected(readUnencodedNumber<uint64_t>()));
420+
uint32_t NameSize =
421+
cantFail(errorOrToExpected(readUnsignedNumber<uint32_t>()));
422+
StringRef Name = cantFail(errorOrToExpected(readString(NameSize)));
414423

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

@@ -648,12 +662,8 @@ bool MCPseudoProbeDecoder::buildAddress2ProbeMap(
648662

649663
void MCPseudoProbeDecoder::printGUID2FuncDescMap(raw_ostream &OS) {
650664
OS << "Pseudo Probe Desc:\n";
651-
// Make the output deterministic
652-
std::map<uint64_t, MCPseudoProbeFuncDesc> OrderedMap(GUID2FuncDescMap.begin(),
653-
GUID2FuncDescMap.end());
654-
for (auto &I : OrderedMap) {
655-
I.second.print(OS);
656-
}
665+
for (auto &I : GUID2FuncDescMap)
666+
I.print(OS);
657667
}
658668

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

711721
void MCPseudoProbeDecoder::getInlineContextForProbe(

0 commit comments

Comments
 (0)