-
Notifications
You must be signed in to change notification settings - Fork 15k
[MC][NFC] Use vector for GUIDProbeFunctionMap #102905
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[MC][NFC] Use vector for GUIDProbeFunctionMap #102905
Conversation
Created using spr 1.3.5 [skip ci]
Created using spr 1.3.5
|
@llvm/pr-subscribers-mc @llvm/pr-subscribers-bolt Author: Amir Ayupov (aaupov) ChangesReplace unordered_map with a vector. Pre-parse the section to statically Reduces peak RSS of pseudo probe parsing from 9.08 GiB to 8.89 GiB as Test Plan: Full diff: https://github.com/llvm/llvm-project/pull/102905.diff 3 Files Affected:
diff --git a/bolt/lib/Rewrite/PseudoProbeRewriter.cpp b/bolt/lib/Rewrite/PseudoProbeRewriter.cpp
index 95a0d2c1fbe59..77605f1b47b11 100644
--- a/bolt/lib/Rewrite/PseudoProbeRewriter.cpp
+++ b/bolt/lib/Rewrite/PseudoProbeRewriter.cpp
@@ -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]);
diff --git a/llvm/include/llvm/MC/MCPseudoProbe.h b/llvm/include/llvm/MC/MCPseudoProbe.h
index 6021dd38e9d9c..64b73b5b932e9 100644
--- a/llvm/include/llvm/MC/MCPseudoProbe.h
+++ b/llvm/include/llvm/MC/MCPseudoProbe.h
@@ -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>
@@ -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){};
@@ -100,8 +101,15 @@ 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 {
+ return llvm::lower_bound(
+ *this, GUID, [](const MCPseudoProbeFuncDesc &Desc, uint64_t GUID) {
+ return Desc.FuncGUID < GUID;
+ });
+ }
+};
class MCDecodedPseudoProbeInlineTree;
@@ -382,6 +390,8 @@ class MCPseudoProbeDecoder {
// GUID to PseudoProbeFuncDesc map.
GUIDProbeFunctionMap GUID2FuncDescMap;
+ BumpPtrAllocator FuncNameAllocator;
+
// Address to probes map.
AddressProbesMap Address2ProbesMap;
diff --git a/llvm/lib/MC/MCPseudoProbe.cpp b/llvm/lib/MC/MCPseudoProbe.cpp
index 45fe95e176ff2..e5b66200b4d2e 100644
--- a/llvm/lib/MC/MCPseudoProbe.cpp
+++ b/llvm/lib/MC/MCPseudoProbe.cpp
@@ -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) {
@@ -390,32 +390,41 @@ 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)
+ if (!readUnencodedNumber<uint64_t>())
return false;
-
- auto ErrorOrHash = readUnencodedNumber<uint64_t>();
- if (!ErrorOrHash)
+ 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)
+ 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");
+ llvm::sort(GUID2FuncDescMap, [](const auto &LHS, const auto &RHS) {
+ return LHS.FuncGUID < RHS.FuncGUID;
+ });
return true;
}
@@ -648,12 +657,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,
@@ -705,7 +710,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(
|
Created using spr 1.3.4 [skip ci]
llvm/include/llvm/MC/MCPseudoProbe.h
Outdated
| auto find(uint64_t GUID) const { | ||
| return llvm::lower_bound( | ||
| *this, GUID, [](const MCPseudoProbeFuncDesc &Desc, uint64_t GUID) { | ||
| return Desc.FuncGUID < GUID; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is similar to the previous PR. we need to make sure return end() when GUID doesn't exist. (this case did happen before #98127)
Created using spr 1.3.4 [skip ci]
Created using spr 1.3.4
Created using spr 1.3.4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks.
Created using spr 1.3.4 [skip ci]
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: #102905
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: