Allow building heatmaps from basic sampled events with `-nl`.

I find that this is useful for finding event hotspots.

Reviewed By: rafauler

Differential Revision: https://reviews.llvm.org/D123067
This commit is contained in:
Rahman Lavaee 2022-04-11 14:39:41 -07:00
parent fe2478d44e
commit 0c13d97e2b
2 changed files with 48 additions and 28 deletions

View File

@ -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:

View File

@ -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();
// 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;
if (opts::BasicAggregation) {
ErrorOr<PerfBasicSample> SampleRes = parseBasicSample();
if (std::error_code EC = SampleRes.getError()) {
if (EC == errc::no_such_process)
continue;
return EC;
}
NextLBR = &LBR;
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;
}
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();
}
if (!Sample.LBR.empty()) {
HM.registerAddress(Sample.LBR.front().To);
HM.registerAddress(Sample.LBR.back().From);
}
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);
}