Skip to content

Commit

Permalink
Allow building heatmaps from basic sampled events with -nl.
Browse files Browse the repository at this point in the history
I find that this is useful for finding event hotspots.

Reviewed By: rafauler

Differential Revision: https://reviews.llvm.org/D123067
  • Loading branch information
rlavaee committed Apr 11, 2022
1 parent fe2478d commit 0c13d97
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 27 deletions.
6 changes: 4 additions & 2 deletions bolt/docs/Heatmaps.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ or if you want to monitor the existing process(es):
$ perf record -e cycles:u -j any,u [-p PID|-a] -- sleep <interval>
```

Note that at the moment running with LBR (`-j any,u` or `-b`) is
a requirement.
Running with LBR (`-j any,u` or `-b`) is recommended. Heatmaps can be generated
from basic events by using the llvm-bolt-heatmap option `-nl` (no LBR) but
such heatmaps do not have the coverage provided by LBR and may only be useful
for finding event hotspots at larger code block granularities.

Once the run is complete, and `perf.data` is generated, run llvm-bolt-heatmap:

Expand Down
68 changes: 43 additions & 25 deletions bolt/lib/Profile/DataAggregator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1296,37 +1296,55 @@ std::error_code DataAggregator::printLBRHeatMap() {
uint64_t NumTotalSamples = 0;

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();
if (opts::BasicAggregation) {
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++;
} else {
ErrorOr<PerfBranchSample> SampleRes = parseBranchSample();
if (std::error_code EC = SampleRes.getError()) {
if (EC == errc::no_such_process)
continue;
return EC;
}

// 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;
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;
}
NextLBR = &LBR;
}
if (!Sample.LBR.empty()) {
HM.registerAddress(Sample.LBR.front().To);
HM.registerAddress(Sample.LBR.back().From);
if (!Sample.LBR.empty()) {
HM.registerAddress(Sample.LBR.front().To);
HM.registerAddress(Sample.LBR.back().From);
}
NumTotalSamples += Sample.LBR.size();
}
NumTotalSamples += Sample.LBR.size();
}

if (!NumTotalSamples) {
errs() << "HEATMAP-ERROR: no LBR traces detected in profile. "
"Cannot build heatmap.\n";
if (!opts::BasicAggregation) {
errs() << "HEATMAP-ERROR: no LBR traces detected in profile. "
"Cannot build heatmap. Use -nl for building heatmap from "
"basic events.\n";
} else {
errs() << "HEATMAP-ERROR: no samples detected in profile. "
"Cannot build heatmap.";
}
exit(1);
}

Expand Down

0 comments on commit 0c13d97

Please sign in to comment.