Skip to content

[BOLT][heatmap] Use parsed basic/branch events #136531

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

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions bolt/include/bolt/Profile/Heatmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ class Heatmap {
}

/// Register a single sample at \p Address.
void registerAddress(uint64_t Address) {
void registerAddress(uint64_t Address, uint64_t Count) {
if (!ignoreAddress(Address))
++Map[Address / BucketSize];
Map[Address / BucketSize] += Count;
}

/// Register \p Count samples at [\p StartAddress, \p EndAddress ].
Expand Down
82 changes: 27 additions & 55 deletions bolt/lib/Profile/DataAggregator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,10 @@ Error DataAggregator::preprocessProfile(BinaryContext &BC) {
filterBinaryMMapInfo();
prepareToParse("events", MainEventsPPI, ErrorCallback);

if ((!opts::BasicAggregation && parseBranchEvents()) ||
(opts::BasicAggregation && parseBasicEvents()))
errs() << "PERF2BOLT: failed to parse samples\n";

if (opts::HeatmapMode) {
if (std::error_code EC = printLBRHeatMap()) {
errs() << "ERROR: failed to print heat map: " << EC.message() << '\n';
Expand All @@ -505,10 +509,6 @@ Error DataAggregator::preprocessProfile(BinaryContext &BC) {
exit(0);
}

if ((!opts::BasicAggregation && parseBranchEvents()) ||
(opts::BasicAggregation && parseBasicEvents()))
errs() << "PERF2BOLT: failed to parse samples\n";

// Special handling for memory events
if (prepareToParse("mem events", MemEventsPPI, MemEventsErrorCallback))
return Error::success();
Expand Down Expand Up @@ -1307,53 +1307,6 @@ std::error_code DataAggregator::printLBRHeatMap() {
}
Heatmap HM(opts::HeatmapBlock, opts::HeatmapMinAddress,
opts::HeatmapMaxAddress, getTextSections(BC));
uint64_t NumTotalSamples = 0;

if (opts::BasicAggregation) {
while (hasData()) {
ErrorOr<PerfBasicSample> SampleRes = parseBasicSample();
if (std::error_code EC = SampleRes.getError()) {
if (EC == errc::no_such_process)
continue;
return EC;
}
PerfBasicSample &Sample = SampleRes.get();
HM.registerAddress(Sample.PC);
NumTotalSamples++;
}
outs() << "HEATMAP: read " << NumTotalSamples << " basic samples\n";
} else {
while (hasData()) {
ErrorOr<PerfBranchSample> SampleRes = parseBranchSample();
if (std::error_code EC = SampleRes.getError()) {
if (EC == errc::no_such_process)
continue;
return EC;
}

PerfBranchSample &Sample = SampleRes.get();

// LBRs are stored in reverse execution order. NextLBR refers to the next
// executed branch record.
const LBREntry *NextLBR = nullptr;
for (const LBREntry &LBR : Sample.LBR) {
if (NextLBR) {
// Record fall-through trace.
const uint64_t TraceFrom = LBR.To;
const uint64_t TraceTo = NextLBR->From;
++FallthroughLBRs[Trace(TraceFrom, TraceTo)].InternCount;
}
NextLBR = &LBR;
}
if (!Sample.LBR.empty()) {
HM.registerAddress(Sample.LBR.front().To);
HM.registerAddress(Sample.LBR.back().From);
}
NumTotalSamples += Sample.LBR.size();
}
outs() << "HEATMAP: read " << NumTotalSamples << " LBR samples\n";
outs() << "HEATMAP: " << FallthroughLBRs.size() << " unique traces\n";
}

if (!NumTotalSamples) {
if (opts::BasicAggregation) {
Expand All @@ -1369,10 +1322,14 @@ std::error_code DataAggregator::printLBRHeatMap() {

outs() << "HEATMAP: building heat map...\n";

// Register basic samples and perf LBR addresses not covered by fallthroughs.
for (const auto &[PC, Hits] : BasicSamples)
HM.registerAddress(PC, Hits);
for (const auto &LBR : FallthroughLBRs) {
const Trace &Trace = LBR.first;
const FTInfo &Info = LBR.second;
HM.registerAddressRange(Trace.From, Trace.To, Info.InternCount);
HM.registerAddressRange(Trace.From, Trace.To,
Info.InternCount + Info.ExternCount);
}

if (HM.getNumInvalidRanges())
Expand Down Expand Up @@ -1418,7 +1375,10 @@ void DataAggregator::parseLBRSample(const PerfBranchSample &Sample,
const uint64_t TraceTo = NextLBR->From;
const BinaryFunction *TraceBF =
getBinaryFunctionContainingAddress(TraceFrom);
if (TraceBF && TraceBF->containsAddress(TraceTo)) {
if (opts::HeatmapMode) {
FTInfo &Info = FallthroughLBRs[Trace(TraceFrom, TraceTo)];
++Info.InternCount;
} else if (TraceBF && TraceBF->containsAddress(TraceTo)) {
FTInfo &Info = FallthroughLBRs[Trace(TraceFrom, TraceTo)];
if (TraceBF->containsAddress(LBR.From))
++Info.InternCount;
Expand Down Expand Up @@ -1452,6 +1412,12 @@ void DataAggregator::parseLBRSample(const PerfBranchSample &Sample,
}
NextLBR = &LBR;

// Record branches outside binary functions for heatmap.
if (opts::HeatmapMode) {
TakenBranchInfo &Info = BranchLBRs[Trace(LBR.From, LBR.To)];
++Info.TakenCount;
continue;
}
uint64_t From = getBinaryFunctionContainingAddress(LBR.From) ? LBR.From : 0;
uint64_t To = getBinaryFunctionContainingAddress(LBR.To) ? LBR.To : 0;
if (!From && !To)
Expand All @@ -1460,6 +1426,12 @@ void DataAggregator::parseLBRSample(const PerfBranchSample &Sample,
++Info.TakenCount;
Info.MispredCount += LBR.Mispred;
}
// Record LBR addresses not covered by fallthroughs (bottom-of-stack source
// and top-of-stack target) as basic samples for heatmap.
if (opts::HeatmapMode && !Sample.LBR.empty()) {
++BasicSamples[Sample.LBR.front().To];
++BasicSamples[Sample.LBR.back().From];
}
}

void DataAggregator::printColdSamplesDiagnostic() const {
Expand Down Expand Up @@ -1636,13 +1608,15 @@ std::error_code DataAggregator::parseBasicEvents() {

if (!Sample->PC)
continue;
++NumTotalSamples;

if (BinaryFunction *BF = getBinaryFunctionContainingAddress(Sample->PC))
BF->setHasProfileAvailable();

++BasicSamples[Sample->PC];
EventNames.insert(Sample->EventName);
}
outs() << "PERF2BOLT: read " << NumTotalSamples << " basic samples\n";

return std::error_code();
}
Expand All @@ -1655,7 +1629,6 @@ void DataAggregator::processBasicEvents() {
for (auto &Sample : BasicSamples) {
const uint64_t PC = Sample.first;
const uint64_t HitCount = Sample.second;
NumTotalSamples += HitCount;
BinaryFunction *Func = getBinaryFunctionContainingAddress(PC);
if (!Func) {
OutOfRangeSamples += HitCount;
Expand All @@ -1664,7 +1637,6 @@ void DataAggregator::processBasicEvents() {

doBasicSample(*Func, PC, HitCount);
}
outs() << "PERF2BOLT: read " << NumTotalSamples << " samples\n";

printBasicSamplesDiagnostics(OutOfRangeSamples);
}
Expand Down
Loading