Skip to content

Commit f2351d9

Browse files
authored
[BOLT][heatmap] Use parsed basic/branch events (#136531)
Remove duplicate profile parsing in heatmap construction, switching to using parsed profile. #138798 adds support for using pre-aggregated profile for heatmap construction. Test Plan: added heatmap.test in rafaelauler/bolt-tests@0868850
1 parent e953487 commit f2351d9

File tree

2 files changed

+29
-57
lines changed

2 files changed

+29
-57
lines changed

bolt/include/bolt/Profile/Heatmap.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ class Heatmap {
5757
}
5858

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

6565
/// Register \p Count samples at [\p StartAddress, \p EndAddress ].

bolt/lib/Profile/DataAggregator.cpp

Lines changed: 27 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,10 @@ Error DataAggregator::preprocessProfile(BinaryContext &BC) {
497497
filterBinaryMMapInfo();
498498
prepareToParse("events", MainEventsPPI, ErrorCallback);
499499

500+
if ((!opts::BasicAggregation && parseBranchEvents()) ||
501+
(opts::BasicAggregation && parseBasicEvents()))
502+
errs() << "PERF2BOLT: failed to parse samples\n";
503+
500504
if (opts::HeatmapMode) {
501505
if (std::error_code EC = printLBRHeatMap()) {
502506
errs() << "ERROR: failed to print heat map: " << EC.message() << '\n';
@@ -505,10 +509,6 @@ Error DataAggregator::preprocessProfile(BinaryContext &BC) {
505509
exit(0);
506510
}
507511

508-
if ((!opts::BasicAggregation && parseBranchEvents()) ||
509-
(opts::BasicAggregation && parseBasicEvents()))
510-
errs() << "PERF2BOLT: failed to parse samples\n";
511-
512512
// Special handling for memory events
513513
if (prepareToParse("mem events", MemEventsPPI, MemEventsErrorCallback))
514514
return Error::success();
@@ -1307,53 +1307,6 @@ std::error_code DataAggregator::printLBRHeatMap() {
13071307
}
13081308
Heatmap HM(opts::HeatmapBlock, opts::HeatmapMinAddress,
13091309
opts::HeatmapMaxAddress, getTextSections(BC));
1310-
uint64_t NumTotalSamples = 0;
1311-
1312-
if (opts::BasicAggregation) {
1313-
while (hasData()) {
1314-
ErrorOr<PerfBasicSample> SampleRes = parseBasicSample();
1315-
if (std::error_code EC = SampleRes.getError()) {
1316-
if (EC == errc::no_such_process)
1317-
continue;
1318-
return EC;
1319-
}
1320-
PerfBasicSample &Sample = SampleRes.get();
1321-
HM.registerAddress(Sample.PC);
1322-
NumTotalSamples++;
1323-
}
1324-
outs() << "HEATMAP: read " << NumTotalSamples << " basic samples\n";
1325-
} else {
1326-
while (hasData()) {
1327-
ErrorOr<PerfBranchSample> SampleRes = parseBranchSample();
1328-
if (std::error_code EC = SampleRes.getError()) {
1329-
if (EC == errc::no_such_process)
1330-
continue;
1331-
return EC;
1332-
}
1333-
1334-
PerfBranchSample &Sample = SampleRes.get();
1335-
1336-
// LBRs are stored in reverse execution order. NextLBR refers to the next
1337-
// executed branch record.
1338-
const LBREntry *NextLBR = nullptr;
1339-
for (const LBREntry &LBR : Sample.LBR) {
1340-
if (NextLBR) {
1341-
// Record fall-through trace.
1342-
const uint64_t TraceFrom = LBR.To;
1343-
const uint64_t TraceTo = NextLBR->From;
1344-
++FallthroughLBRs[Trace(TraceFrom, TraceTo)].InternCount;
1345-
}
1346-
NextLBR = &LBR;
1347-
}
1348-
if (!Sample.LBR.empty()) {
1349-
HM.registerAddress(Sample.LBR.front().To);
1350-
HM.registerAddress(Sample.LBR.back().From);
1351-
}
1352-
NumTotalSamples += Sample.LBR.size();
1353-
}
1354-
outs() << "HEATMAP: read " << NumTotalSamples << " LBR samples\n";
1355-
outs() << "HEATMAP: " << FallthroughLBRs.size() << " unique traces\n";
1356-
}
13571310

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

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

1325+
// Register basic samples and perf LBR addresses not covered by fallthroughs.
1326+
for (const auto &[PC, Hits] : BasicSamples)
1327+
HM.registerAddress(PC, Hits);
13721328
for (const auto &LBR : FallthroughLBRs) {
13731329
const Trace &Trace = LBR.first;
13741330
const FTInfo &Info = LBR.second;
1375-
HM.registerAddressRange(Trace.From, Trace.To, Info.InternCount);
1331+
HM.registerAddressRange(Trace.From, Trace.To,
1332+
Info.InternCount + Info.ExternCount);
13761333
}
13771334

13781335
if (HM.getNumInvalidRanges())
@@ -1418,7 +1375,10 @@ void DataAggregator::parseLBRSample(const PerfBranchSample &Sample,
14181375
const uint64_t TraceTo = NextLBR->From;
14191376
const BinaryFunction *TraceBF =
14201377
getBinaryFunctionContainingAddress(TraceFrom);
1421-
if (TraceBF && TraceBF->containsAddress(TraceTo)) {
1378+
if (opts::HeatmapMode) {
1379+
FTInfo &Info = FallthroughLBRs[Trace(TraceFrom, TraceTo)];
1380+
++Info.InternCount;
1381+
} else if (TraceBF && TraceBF->containsAddress(TraceTo)) {
14221382
FTInfo &Info = FallthroughLBRs[Trace(TraceFrom, TraceTo)];
14231383
if (TraceBF->containsAddress(LBR.From))
14241384
++Info.InternCount;
@@ -1452,6 +1412,12 @@ void DataAggregator::parseLBRSample(const PerfBranchSample &Sample,
14521412
}
14531413
NextLBR = &LBR;
14541414

1415+
// Record branches outside binary functions for heatmap.
1416+
if (opts::HeatmapMode) {
1417+
TakenBranchInfo &Info = BranchLBRs[Trace(LBR.From, LBR.To)];
1418+
++Info.TakenCount;
1419+
continue;
1420+
}
14551421
uint64_t From = getBinaryFunctionContainingAddress(LBR.From) ? LBR.From : 0;
14561422
uint64_t To = getBinaryFunctionContainingAddress(LBR.To) ? LBR.To : 0;
14571423
if (!From && !To)
@@ -1460,6 +1426,12 @@ void DataAggregator::parseLBRSample(const PerfBranchSample &Sample,
14601426
++Info.TakenCount;
14611427
Info.MispredCount += LBR.Mispred;
14621428
}
1429+
// Record LBR addresses not covered by fallthroughs (bottom-of-stack source
1430+
// and top-of-stack target) as basic samples for heatmap.
1431+
if (opts::HeatmapMode && !Sample.LBR.empty()) {
1432+
++BasicSamples[Sample.LBR.front().To];
1433+
++BasicSamples[Sample.LBR.back().From];
1434+
}
14631435
}
14641436

14651437
void DataAggregator::printColdSamplesDiagnostic() const {
@@ -1636,13 +1608,15 @@ std::error_code DataAggregator::parseBasicEvents() {
16361608

16371609
if (!Sample->PC)
16381610
continue;
1611+
++NumTotalSamples;
16391612

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

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

16471621
return std::error_code();
16481622
}
@@ -1655,7 +1629,6 @@ void DataAggregator::processBasicEvents() {
16551629
for (auto &Sample : BasicSamples) {
16561630
const uint64_t PC = Sample.first;
16571631
const uint64_t HitCount = Sample.second;
1658-
NumTotalSamples += HitCount;
16591632
BinaryFunction *Func = getBinaryFunctionContainingAddress(PC);
16601633
if (!Func) {
16611634
OutOfRangeSamples += HitCount;
@@ -1664,7 +1637,6 @@ void DataAggregator::processBasicEvents() {
16641637

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

16691641
printBasicSamplesDiagnostics(OutOfRangeSamples);
16701642
}

0 commit comments

Comments
 (0)