[BOLT][NFCI] Report perf script time (#147232)
Leverage `sys::ProcessStatistics` to report the run time and memory usage of perf script processes launched when reading perf data. The reporting is enabled in debug mode with `-debug-only=aggregator`. Switch buildid-list command to non-waiting `launchPerfProcess` to get its runtime as well, unifying it with the rest of perf script processes. Test Plan: NFC
This commit is contained in:
parent
3d6407965d
commit
46e3ec0244
@ -236,8 +236,7 @@ private:
|
|||||||
|
|
||||||
/// Launch a perf subprocess with given args and save output for later
|
/// Launch a perf subprocess with given args and save output for later
|
||||||
/// parsing.
|
/// parsing.
|
||||||
void launchPerfProcess(StringRef Name, PerfProcessInfo &PPI,
|
void launchPerfProcess(StringRef Name, PerfProcessInfo &PPI, StringRef Args);
|
||||||
const char *ArgsString, bool Wait);
|
|
||||||
|
|
||||||
/// Delete all temporary files created to hold the output generated by spawned
|
/// Delete all temporary files created to hold the output generated by spawned
|
||||||
/// subprocesses during the aggregation job
|
/// subprocesses during the aggregation job
|
||||||
|
@ -197,34 +197,27 @@ void DataAggregator::start() {
|
|||||||
|
|
||||||
if (opts::BasicAggregation) {
|
if (opts::BasicAggregation) {
|
||||||
launchPerfProcess("events without LBR", MainEventsPPI,
|
launchPerfProcess("events without LBR", MainEventsPPI,
|
||||||
"script -F pid,event,ip",
|
"script -F pid,event,ip");
|
||||||
/*Wait = */ false);
|
|
||||||
} else if (!opts::ITraceAggregation.empty()) {
|
} else if (!opts::ITraceAggregation.empty()) {
|
||||||
// Disable parsing memory profile from trace data, unless requested by user.
|
// Disable parsing memory profile from trace data, unless requested by user.
|
||||||
if (!opts::ParseMemProfile.getNumOccurrences())
|
if (!opts::ParseMemProfile.getNumOccurrences())
|
||||||
opts::ParseMemProfile = false;
|
opts::ParseMemProfile = false;
|
||||||
|
|
||||||
std::string ItracePerfScriptArgs = llvm::formatv(
|
|
||||||
"script -F pid,brstack --itrace={0}", opts::ITraceAggregation);
|
|
||||||
launchPerfProcess("branch events with itrace", MainEventsPPI,
|
launchPerfProcess("branch events with itrace", MainEventsPPI,
|
||||||
ItracePerfScriptArgs.c_str(),
|
"script -F pid,brstack --itrace=" +
|
||||||
/*Wait = */ false);
|
opts::ITraceAggregation);
|
||||||
} else {
|
} else {
|
||||||
launchPerfProcess("branch events", MainEventsPPI, "script -F pid,brstack",
|
launchPerfProcess("branch events", MainEventsPPI, "script -F pid,brstack");
|
||||||
/*Wait = */ false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts::ParseMemProfile)
|
if (opts::ParseMemProfile)
|
||||||
launchPerfProcess("mem events", MemEventsPPI, "script -F pid,event,addr,ip",
|
launchPerfProcess("mem events", MemEventsPPI,
|
||||||
/*Wait = */ false);
|
"script -F pid,event,addr,ip");
|
||||||
|
|
||||||
launchPerfProcess("process events", MMapEventsPPI,
|
launchPerfProcess("process events", MMapEventsPPI,
|
||||||
"script --show-mmap-events --no-itrace",
|
"script --show-mmap-events --no-itrace");
|
||||||
/*Wait = */ false);
|
|
||||||
|
|
||||||
launchPerfProcess("task events", TaskEventsPPI,
|
launchPerfProcess("task events", TaskEventsPPI,
|
||||||
"script --show-task-events --no-itrace",
|
"script --show-task-events --no-itrace");
|
||||||
/*Wait = */ false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataAggregator::abort() {
|
void DataAggregator::abort() {
|
||||||
@ -246,13 +239,13 @@ void DataAggregator::abort() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DataAggregator::launchPerfProcess(StringRef Name, PerfProcessInfo &PPI,
|
void DataAggregator::launchPerfProcess(StringRef Name, PerfProcessInfo &PPI,
|
||||||
const char *ArgsString, bool Wait) {
|
StringRef Args) {
|
||||||
SmallVector<StringRef, 4> Argv;
|
SmallVector<StringRef, 4> Argv;
|
||||||
|
|
||||||
outs() << "PERF2BOLT: spawning perf job to read " << Name << '\n';
|
outs() << "PERF2BOLT: spawning perf job to read " << Name << '\n';
|
||||||
Argv.push_back(PerfPath.data());
|
Argv.push_back(PerfPath.data());
|
||||||
|
|
||||||
StringRef(ArgsString).split(Argv, ' ');
|
Args.split(Argv, ' ');
|
||||||
Argv.push_back("-f");
|
Argv.push_back("-f");
|
||||||
Argv.push_back("-i");
|
Argv.push_back("-i");
|
||||||
Argv.push_back(Filename.c_str());
|
Argv.push_back(Filename.c_str());
|
||||||
@ -286,46 +279,38 @@ void DataAggregator::launchPerfProcess(StringRef Name, PerfProcessInfo &PPI,
|
|||||||
<< "\n";
|
<< "\n";
|
||||||
});
|
});
|
||||||
|
|
||||||
if (Wait)
|
|
||||||
PPI.PI.ReturnCode = sys::ExecuteAndWait(PerfPath.data(), Argv,
|
|
||||||
/*envp*/ std::nullopt, Redirects);
|
|
||||||
else
|
|
||||||
PPI.PI = sys::ExecuteNoWait(PerfPath.data(), Argv, /*envp*/ std::nullopt,
|
PPI.PI = sys::ExecuteNoWait(PerfPath.data(), Argv, /*envp*/ std::nullopt,
|
||||||
Redirects);
|
Redirects);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataAggregator::processFileBuildID(StringRef FileBuildID) {
|
void DataAggregator::processFileBuildID(StringRef FileBuildID) {
|
||||||
|
auto WarningCallback = [](int ReturnCode, StringRef ErrBuf) {
|
||||||
|
errs() << "PERF-ERROR: return code " << ReturnCode << "\n" << ErrBuf;
|
||||||
|
};
|
||||||
|
|
||||||
PerfProcessInfo BuildIDProcessInfo;
|
PerfProcessInfo BuildIDProcessInfo;
|
||||||
launchPerfProcess("buildid list",
|
launchPerfProcess("buildid list", BuildIDProcessInfo, "buildid-list");
|
||||||
BuildIDProcessInfo,
|
if (prepareToParse("buildid", BuildIDProcessInfo, WarningCallback))
|
||||||
"buildid-list",
|
|
||||||
/*Wait = */true);
|
|
||||||
|
|
||||||
if (BuildIDProcessInfo.PI.ReturnCode != 0) {
|
|
||||||
ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
|
|
||||||
MemoryBuffer::getFileOrSTDIN(BuildIDProcessInfo.StderrPath.data());
|
|
||||||
StringRef ErrBuf = (*MB)->getBuffer();
|
|
||||||
|
|
||||||
errs() << "PERF-ERROR: return code " << BuildIDProcessInfo.PI.ReturnCode
|
|
||||||
<< '\n';
|
|
||||||
errs() << ErrBuf;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
|
|
||||||
MemoryBuffer::getFileOrSTDIN(BuildIDProcessInfo.StdoutPath.data());
|
|
||||||
if (std::error_code EC = MB.getError()) {
|
|
||||||
errs() << "Cannot open " << BuildIDProcessInfo.StdoutPath.data() << ": "
|
|
||||||
<< EC.message() << "\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileBuf = std::move(*MB);
|
|
||||||
ParsingBuf = FileBuf->getBuffer();
|
|
||||||
|
|
||||||
std::optional<StringRef> FileName = getFileNameForBuildID(FileBuildID);
|
std::optional<StringRef> FileName = getFileNameForBuildID(FileBuildID);
|
||||||
if (!FileName) {
|
if (FileName && *FileName == sys::path::filename(BC->getFilename())) {
|
||||||
if (hasAllBuildIDs()) {
|
outs() << "PERF2BOLT: matched build-id and file name\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FileName) {
|
||||||
|
errs() << "PERF2BOLT-WARNING: build-id matched a different file name\n";
|
||||||
|
BuildIDBinaryName = std::string(*FileName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasAllBuildIDs()) {
|
||||||
|
errs() << "PERF2BOLT-WARNING: build-id will not be checked because perf "
|
||||||
|
"data was recorded without it\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
errs() << "PERF2BOLT-ERROR: failed to match build-id from perf output. "
|
errs() << "PERF2BOLT-ERROR: failed to match build-id from perf output. "
|
||||||
"This indicates the input binary supplied for data aggregation "
|
"This indicates the input binary supplied for data aggregation "
|
||||||
"is not the same recorded by perf when collecting profiling "
|
"is not the same recorded by perf when collecting profiling "
|
||||||
@ -333,17 +318,6 @@ void DataAggregator::processFileBuildID(StringRef FileBuildID) {
|
|||||||
"Use -ignore-build-id option to override.\n";
|
"Use -ignore-build-id option to override.\n";
|
||||||
if (!opts::IgnoreBuildID)
|
if (!opts::IgnoreBuildID)
|
||||||
abort();
|
abort();
|
||||||
} else {
|
|
||||||
errs() << "PERF2BOLT-WARNING: build-id will not be checked because perf "
|
|
||||||
"data was recorded without it\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (*FileName != llvm::sys::path::filename(BC->getFilename())) {
|
|
||||||
errs() << "PERF2BOLT-WARNING: build-id matched a different file name\n";
|
|
||||||
BuildIDBinaryName = std::string(*FileName);
|
|
||||||
} else {
|
|
||||||
outs() << "PERF2BOLT: matched build-id and file name\n";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DataAggregator::checkPerfDataMagic(StringRef FileName) {
|
bool DataAggregator::checkPerfDataMagic(StringRef FileName) {
|
||||||
@ -432,7 +406,8 @@ int DataAggregator::prepareToParse(StringRef Name, PerfProcessInfo &Process,
|
|||||||
std::string Error;
|
std::string Error;
|
||||||
outs() << "PERF2BOLT: waiting for perf " << Name
|
outs() << "PERF2BOLT: waiting for perf " << Name
|
||||||
<< " collection to finish...\n";
|
<< " collection to finish...\n";
|
||||||
sys::ProcessInfo PI = sys::Wait(Process.PI, std::nullopt, &Error);
|
std::optional<sys::ProcessStatistics> PS;
|
||||||
|
sys::ProcessInfo PI = sys::Wait(Process.PI, std::nullopt, &Error, &PS);
|
||||||
|
|
||||||
if (!Error.empty()) {
|
if (!Error.empty()) {
|
||||||
errs() << "PERF-ERROR: " << PerfPath << ": " << Error << "\n";
|
errs() << "PERF-ERROR: " << PerfPath << ": " << Error << "\n";
|
||||||
@ -440,6 +415,15 @@ int DataAggregator::prepareToParse(StringRef Name, PerfProcessInfo &Process,
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LLVM_DEBUG({
|
||||||
|
const float UserSec = 1.f * PS->UserTime.count() / 1e6;
|
||||||
|
const float TotalSec = 1.f * PS->TotalTime.count() / 1e6;
|
||||||
|
const float PeakGiB = 1.f * PS->PeakMemory / (1 << 20);
|
||||||
|
dbgs() << formatv("Finished in {0:f2}s user time, {1:f2}s total time, "
|
||||||
|
"{2:f2} GiB peak RSS\n",
|
||||||
|
UserSec, TotalSec, PeakGiB);
|
||||||
|
});
|
||||||
|
|
||||||
if (PI.ReturnCode != 0) {
|
if (PI.ReturnCode != 0) {
|
||||||
ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorMB =
|
ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorMB =
|
||||||
MemoryBuffer::getFileOrSTDIN(Process.StderrPath.data());
|
MemoryBuffer::getFileOrSTDIN(Process.StderrPath.data());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user