Skip to content

Commit

Permalink
[Clang] Add a new clang option "-ftime-trace=<value>"
Browse files Browse the repository at this point in the history
The time profiler traces the stages during the clang compile
process. Each compiling stage of a single source file
corresponds to a separately .json file which holds its
time tracing data. However, the .json files are stored in the
same path/directory as its corresponding stage's '-o' option.
For example, if we compile the "demo.cc" to "demo.o" with option
"-o /tmp/demo.o", the time trace data file path is "/tmp/demo.json".

A typical c++ project can contain multiple source files in different
path, but all the json files' paths can be a mess.

The option "-ftime-trace=<value>" allows you to specify where the json
files should be stored. This allows the users to place the time trace
data files of interest in the desired location for further data analysis.

Usage:
    - clang/clang++ -ftime-trace ...
    - clang/clang++ -ftime-trace=the-directory-you-want ...
    - clang/clang++ -ftime-trace=the-directory-you-want/ ...
    - clang/clang++ -ftime-trace=the-full-file-path-you-want ...

Differential Revision: https://reviews.llvm.org/D128048
  • Loading branch information
An-DJ committed Jul 15, 2022
1 parent 883e83d commit f5d9de8
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 1 deletion.
9 changes: 9 additions & 0 deletions clang/include/clang/Driver/Options.td
Expand Up @@ -2857,6 +2857,15 @@ def ftime_trace_granularity_EQ : Joined<["-"], "ftime-trace-granularity=">, Grou
HelpText<"Minimum time granularity (in microseconds) traced by time profiler">,
Flags<[CC1Option, CoreOption]>,
MarshallingInfoInt<FrontendOpts<"TimeTraceGranularity">, "500u">;
def ftime_trace_EQ : Joined<["-"], "ftime-trace=">, Group<f_Group>,
HelpText<"Turn on time profiler. Generates JSON file based on output filename. "
"Specify the path which stores the tracing output file.">,
DocBrief<[{
Turn on time profiler. Generates JSON file based on output filename. Results
can be analyzed with chrome://tracing or `Speedscope App
<https://www.speedscope.app>`_ for flamegraph visualization.}]>,
Flags<[CC1Option, CoreOption]>,
MarshallingInfoString<FrontendOpts<"TimeTracePath">>;
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>,
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Frontend/FrontendOptions.h
Expand Up @@ -499,6 +499,9 @@ class FrontendOptions {
/// Minimum time granularity (in microseconds) traced by time profiler.
unsigned TimeTraceGranularity;

/// Path which stores the output files for -ftime-trace
std::string TimeTracePath;

public:
FrontendOptions()
: DisableFree(false), RelocatablePCH(false), ShowHelp(false),
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Expand Up @@ -6230,6 +6230,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_ftime_report_EQ);
Args.AddLastArg(CmdArgs, options::OPT_ftime_trace);
Args.AddLastArg(CmdArgs, options::OPT_ftime_trace_granularity_EQ);
Args.AddLastArg(CmdArgs, options::OPT_ftime_trace_EQ);
Args.AddLastArg(CmdArgs, options::OPT_ftrapv);
Args.AddLastArg(CmdArgs, options::OPT_malign_double);
Args.AddLastArg(CmdArgs, options::OPT_fno_temp_file);
Expand Down
14 changes: 14 additions & 0 deletions clang/test/Driver/check-time-trace.cpp
Expand Up @@ -2,6 +2,20 @@
// RUN: cat %T/check-time-trace.json \
// RUN: | %python -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \
// RUN: | FileCheck %s
// RUN: %clangxx -S -ftime-trace=%T/new-name.json -ftime-trace-granularity=0 -o %T/check-time-trace %s
// RUN: cat %T/new-name.json \
// RUN: | %python -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \
// RUN: | FileCheck %s
// RUN: rm -rf %T/output1 && mkdir %T/output1
// RUN: %clangxx -S -ftime-trace=%T/output1 -ftime-trace-granularity=0 -o %T/check-time-trace %s
// RUN: cat %T/output1/check-time-trace.json \
// RUN: | %python -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \
// RUN: | FileCheck %s
// RUN: rm -rf %T/output2 && mkdir %T/output2
// RUN: %clangxx -S -ftime-trace=%T/output2/ -ftime-trace-granularity=0 -o %T/check-time-trace %s
// RUN: cat %T/output2/check-time-trace.json \
// RUN: | %python -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \
// RUN: | FileCheck %s

// CHECK: "beginningOfTime": {{[0-9]{16},}}
// CHECK-NEXT: "traceEvents": [
Expand Down
11 changes: 10 additions & 1 deletion clang/tools/driver/cc1_main.cpp
Expand Up @@ -212,7 +212,9 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
bool Success = CompilerInvocation::CreateFromArgs(Clang->getInvocation(),
Argv, Diags, Argv0);

if (Clang->getFrontendOpts().TimeTrace) {
if (Clang->getFrontendOpts().TimeTrace ||
!Clang->getFrontendOpts().TimeTracePath.empty()) {
Clang->getFrontendOpts().TimeTrace = 1;
llvm::timeTraceProfilerInitialize(
Clang->getFrontendOpts().TimeTraceGranularity, Argv0);
}
Expand Down Expand Up @@ -256,6 +258,13 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
if (llvm::timeTraceProfilerEnabled()) {
SmallString<128> Path(Clang->getFrontendOpts().OutputFile);
llvm::sys::path::replace_extension(Path, "json");
if (!Clang->getFrontendOpts().TimeTracePath.empty()) {
// replace the suffix to '.json' directly
SmallString<128> TracePath(Clang->getFrontendOpts().TimeTracePath);
if (llvm::sys::fs::is_directory(TracePath))
llvm::sys::path::append(TracePath, llvm::sys::path::filename(Path));
Path.assign(TracePath);
}
if (auto profilerOutput = Clang->createOutputFile(
Path.str(), /*Binary=*/false, /*RemoveFileOnSignal=*/false,
/*useTemporary=*/false)) {
Expand Down

0 comments on commit f5d9de8

Please sign in to comment.