[clang] 92d7a84 - [Driver] Add option -fproc-stat-report
Serge Pavlov via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 12 23:16:24 PST 2020
Author: Serge Pavlov
Date: 2020-11-13T14:15:42+07:00
New Revision: 92d7a84e128a20cd23e3129dee82c48f1750966a
URL: https://github.com/llvm/llvm-project/commit/92d7a84e128a20cd23e3129dee82c48f1750966a
DIFF: https://github.com/llvm/llvm-project/commit/92d7a84e128a20cd23e3129dee82c48f1750966a.diff
LOG: [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
Added:
clang/test/Driver/report-stat.c
Modified:
clang/docs/UsersManual.rst
clang/include/clang/Driver/Job.h
clang/include/clang/Driver/Options.td
clang/lib/Driver/Driver.cpp
clang/lib/Driver/Job.cpp
Removed:
################################################################################
diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
index 9601ff48c777..2c59ba929ef4 100644
--- a/clang/docs/UsersManual.rst
+++ b/clang/docs/UsersManual.rst
@@ -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
diff erent
+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
diff erent 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.
diff --git a/clang/include/clang/Driver/Job.h b/clang/include/clang/Driver/Job.h
index 8a348c8048d0..199387cddd5c 100644
--- a/clang/include/clang/Driver/Job.h
+++ b/clang/include/clang/Driver/Job.h
@@ -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 @@ class Command {
return OutputFilenames;
}
+ Optional<llvm::sys::ProcessStatistics> getProcessStatistics() const {
+ return ProcStat;
+ }
+
protected:
/// Optionally print the filenames to be compiled
void PrintFileNames() const;
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 245e6765d613..2d22151c6496 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -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">;
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 97d411d8e9f4..bcea01126e0d 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -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() ||
diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp
index de2c2350f8d1..911fd5df3ca2 100644
--- a/clang/lib/Driver/Job.cpp
+++ b/clang/lib/Driver/Job.cpp
@@ -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,
diff --git a/clang/test/Driver/report-stat.c b/clang/test/Driver/report-stat.c
new file mode 100644
index 000000000000..4b53f90d8733
--- /dev/null
+++ b/clang/test/Driver/report-stat.c
@@ -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]+}}
More information about the cfe-commits
mailing list