[Driver] Add option -fproc-stat-report
The new option `-fproc-stat-info=<file>` can be used to generate report about used memory and execution tile of each stage of compilation. Documentation for this option can be found in `UserManual.rst`. The option can be used in parallel builds. Differential Revision: https://reviews.llvm.org/D78903
This commit is contained in:
parent
98f70e94e0
commit
92d7a84e12
|
@ -747,6 +747,51 @@ Current limitations
|
|||
translated from debug annotations. That translation can be lossy,
|
||||
which results in some remarks having no location information.
|
||||
|
||||
Options to Emit Resource Consumption Reports
|
||||
--------------------------------------------
|
||||
|
||||
These are options that report execution time and consumed memory of different
|
||||
compilations steps.
|
||||
|
||||
.. option:: -fproc-stat-report=
|
||||
|
||||
This option requests driver to print used memory and execution time of each
|
||||
compilation step. The ``clang`` driver during execution calls different tools,
|
||||
like compiler, assembler, linker etc. With this option the driver reports
|
||||
total execution time, the execution time spent in user mode and peak memory
|
||||
usage of each the called tool. Value of the option specifies where the report
|
||||
is sent to. If it specifies a regular file, the data are saved to this file in
|
||||
CSV format:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ clang -fproc-stat-report=abc foo.c
|
||||
$ cat abc
|
||||
clang-11,"/tmp/foo-123456.o",92000,84000,87536
|
||||
ld,"a.out",900,8000,53568
|
||||
|
||||
The data on each row represent:
|
||||
|
||||
* file name of the tool executable,
|
||||
* output file name in quotes,
|
||||
* total execution time in microseconds,
|
||||
* execution time in user mode in microseconds,
|
||||
* peak memory usage in Kb.
|
||||
|
||||
It is possible to specify this option without any value. In this case statistics
|
||||
is printed on standard output in human readable format:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ clang -fproc-stat-report foo.c
|
||||
clang-11: output=/tmp/foo-855a8e.o, total=68.000 ms, user=60.000 ms, mem=86920 Kb
|
||||
ld: output=a.out, total=8.000 ms, user=4.000 ms, mem=52320 Kb
|
||||
|
||||
The report file specified in the option is locked for write, so this option
|
||||
can be used to collect statistics in parallel builds. The report file is not
|
||||
cleared, new data is appended to it, thus making posible to accumulate build
|
||||
statistics.
|
||||
|
||||
Other Options
|
||||
-------------
|
||||
Clang options that don't fit neatly into other categories.
|
||||
|
|
|
@ -140,6 +140,9 @@ class Command {
|
|||
/// See Command::setEnvironment
|
||||
std::vector<const char *> Environment;
|
||||
|
||||
/// Information on executable run provided by OS.
|
||||
mutable Optional<llvm::sys::ProcessStatistics> ProcStat;
|
||||
|
||||
/// When a response file is needed, we try to put most arguments in an
|
||||
/// exclusive file, while others remains as regular command line arguments.
|
||||
/// This functions fills a vector with the regular command line arguments,
|
||||
|
@ -212,6 +215,10 @@ public:
|
|||
return OutputFilenames;
|
||||
}
|
||||
|
||||
Optional<llvm::sys::ProcessStatistics> getProcessStatistics() const {
|
||||
return ProcStat;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Optionally print the filenames to be compiled
|
||||
void PrintFileNames() const;
|
||||
|
|
|
@ -1964,6 +1964,10 @@ can be analyzed with chrome://tracing or `Speedscope App
|
|||
def ftime_trace_granularity_EQ : Joined<["-"], "ftime-trace-granularity=">, Group<f_Group>,
|
||||
HelpText<"Minimum time granularity (in microseconds) traced by time profiler">,
|
||||
Flags<[CC1Option, CoreOption]>;
|
||||
def fproc_stat_report : Joined<["-"], "fproc-stat-report">, Group<f_Group>,
|
||||
HelpText<"Print subprocess statistics">;
|
||||
def fproc_stat_report_EQ : Joined<["-"], "fproc-stat-report=">, Group<f_Group>,
|
||||
HelpText<"Save subprocess statistics to the given file">;
|
||||
def ftlsmodel_EQ : Joined<["-"], "ftls-model=">, Group<f_Group>, Flags<[CC1Option]>;
|
||||
def ftrapv : Flag<["-"], "ftrapv">, Group<f_Group>, Flags<[CC1Option]>,
|
||||
HelpText<"Trap on integer overflow">;
|
||||
|
|
|
@ -3926,11 +3926,68 @@ void Driver::BuildJobs(Compilation &C) const {
|
|||
/*TargetDeviceOffloadKind*/ Action::OFK_None);
|
||||
}
|
||||
|
||||
// If we have more than one job, then disable integrated-cc1 for now.
|
||||
if (C.getJobs().size() > 1)
|
||||
StringRef StatReportFile;
|
||||
bool PrintProcessStat = false;
|
||||
if (const Arg *A = C.getArgs().getLastArg(options::OPT_fproc_stat_report_EQ))
|
||||
StatReportFile = A->getValue();
|
||||
if (C.getArgs().hasArg(options::OPT_fproc_stat_report))
|
||||
PrintProcessStat = true;
|
||||
|
||||
// If we have more than one job, then disable integrated-cc1 for now. Do this
|
||||
// also when we need to report process execution statistics.
|
||||
if (C.getJobs().size() > 1 || !StatReportFile.empty() || PrintProcessStat)
|
||||
for (auto &J : C.getJobs())
|
||||
J.InProcess = false;
|
||||
|
||||
if (!StatReportFile.empty() || PrintProcessStat) {
|
||||
C.setPostCallback([=](const Command &Cmd, int Res) {
|
||||
Optional<llvm::sys::ProcessStatistics> ProcStat =
|
||||
Cmd.getProcessStatistics();
|
||||
if (!ProcStat)
|
||||
return;
|
||||
if (PrintProcessStat) {
|
||||
using namespace llvm;
|
||||
// Human readable output.
|
||||
outs() << sys::path::filename(Cmd.getExecutable()) << ": "
|
||||
<< "output=";
|
||||
if (Cmd.getOutputFilenames().empty())
|
||||
outs() << "\"\"";
|
||||
else
|
||||
outs() << Cmd.getOutputFilenames().front();
|
||||
outs() << ", total="
|
||||
<< format("%.3f", ProcStat->TotalTime.count() / 1000.) << " ms"
|
||||
<< ", user="
|
||||
<< format("%.3f", ProcStat->UserTime.count() / 1000.) << " ms"
|
||||
<< ", mem=" << ProcStat->PeakMemory << " Kb\n";
|
||||
}
|
||||
if (!StatReportFile.empty()) {
|
||||
// CSV format.
|
||||
std::string Buffer;
|
||||
llvm::raw_string_ostream Out(Buffer);
|
||||
Out << llvm::sys::path::filename(Cmd.getExecutable()) << ',';
|
||||
if (Cmd.getOutputFilenames().empty())
|
||||
Out << "\"\"";
|
||||
else
|
||||
llvm::sys::printArg(Out, Cmd.getOutputFilenames().front(), true);
|
||||
Out << ',' << ProcStat->TotalTime.count() << ','
|
||||
<< ProcStat->UserTime.count() << ',' << ProcStat->PeakMemory
|
||||
<< '\n';
|
||||
Out.flush();
|
||||
std::error_code EC;
|
||||
llvm::raw_fd_ostream OS(StatReportFile, EC, llvm::sys::fs::OF_Append);
|
||||
if (EC)
|
||||
return;
|
||||
auto L = OS.lock();
|
||||
if (!L) {
|
||||
llvm::errs() << "ERROR: Cannot lock file " << StatReportFile << ": "
|
||||
<< toString(L.takeError()) << "\n";
|
||||
return;
|
||||
}
|
||||
OS << Buffer;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// If the user passed -Qunused-arguments or there were errors, don't warn
|
||||
// about any unused arguments.
|
||||
if (Diags.hasErrorOccurred() ||
|
||||
|
|
|
@ -352,8 +352,8 @@ int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
|
|||
|
||||
auto Args = llvm::toStringRefArray(Argv.data());
|
||||
return llvm::sys::ExecuteAndWait(Executable, Args, Env, Redirects,
|
||||
/*secondsToWait*/ 0,
|
||||
/*memoryLimit*/ 0, ErrMsg, ExecutionFailed);
|
||||
/*secondsToWait*/ 0, /*memoryLimit*/ 0,
|
||||
ErrMsg, ExecutionFailed, &ProcStat);
|
||||
}
|
||||
|
||||
CC1Command::CC1Command(const Action &Source, const Tool &Creator,
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
// RUN: %clang -c -fproc-stat-report %s | FileCheck %s
|
||||
// CHECK: clang{{.*}}: output={{.*}}.o, total={{[0-9.]+}} ms, user={{[0-9.]+}} ms, mem={{[0-9]+}} Kb
|
||||
|
||||
// RUN: %clang -c -fproc-stat-report=%t %s
|
||||
// RUN: cat %t | FileCheck --check-prefix=CSV %s
|
||||
// CSV: clang{{.*}},"{{.*}}.o",{{[0-9]+}},{{[0-9]+}},{{[0-9]+}}
|
Loading…
Reference in New Issue