Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===- llvm/Support/TimeProfiler.h - Hierarchical Time Profiler -*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This provides lightweight and dependency-free machinery to trace execution
10
// time around arbitrary code. Two API flavors are available.
11
//
12
// The primary API uses a RAII object to trigger tracing:
13
//
14
// \code
15
//   {
16
//     TimeTraceScope scope("my_event_name");
17
//     ...my code...
18
//   }
19
// \endcode
20
//
21
// If the code to be profiled does not have a natural lexical scope then
22
// it is also possible to start and end events with respect to an implicit
23
// per-thread stack of profiling entries:
24
//
25
// \code
26
//   timeTraceProfilerBegin("my_event_name");
27
//   ...my code...
28
//   timeTraceProfilerEnd();  // must be called on all control flow paths
29
// \endcode
30
//
31
// Time profiling entries can be given an arbitrary name and, optionally,
32
// an arbitrary 'detail' string. The resulting trace will include 'Total'
33
// entries summing the time spent for each name. Thus, it's best to choose
34
// names to be fairly generic, and rely on the detail field to capture
35
// everything else of interest.
36
//
37
// To avoid lifetime issues name and detail strings are copied into the event
38
// entries at their time of creation. Care should be taken to make string
39
// construction cheap to prevent 'Heisenperf' effects. In particular, the
40
// 'detail' argument may be a string-returning closure:
41
//
42
// \code
43
//   int n;
44
//   {
45
//     TimeTraceScope scope("my_event_name",
46
//                          [n]() { return (Twine("x=") + Twine(n)).str(); });
47
//     ...my code...
48
//   }
49
// \endcode
50
// The closure will not be called if tracing is disabled. Otherwise, the
51
// resulting string will be directly moved into the entry.
52
//
53
// The main process should begin with a timeTraceProfilerInitialize, and
54
// finish with timeTraceProfileWrite and timeTraceProfilerCleanup calls.
55
// Each new thread should begin with a timeTraceProfilerInitialize, and
56
// finish with a timeTraceProfilerFinishThread call.
57
//
58
// Timestamps come from std::chrono::stable_clock. Note that threads need
59
// not see the same time from that clock, and the resolution may not be
60
// the best available.
61
//
62
// Currently, there are a number of compatible viewers:
63
//  - chrome://tracing is the original chromium trace viewer.
64
//  - http://ui.perfetto.dev is the replacement for the above, under active
65
//    development by Google as part of the 'Perfetto' project.
66
//  - https://www.speedscope.app/ has also been reported as an option.
67
//
68
// Future work:
69
//  - Support akin to LLVM_DEBUG for runtime enable/disable of named tracing
70
//    families for non-debug builds which wish to support optional tracing.
71
//  - Evaluate the detail closures at profile write time to avoid
72
//    stringification costs interfering with tracing.
73
//
74
//===----------------------------------------------------------------------===//
75
 
76
#ifndef LLVM_SUPPORT_TIMEPROFILER_H
77
#define LLVM_SUPPORT_TIMEPROFILER_H
78
 
79
#include "llvm/ADT/STLFunctionalExtras.h"
80
#include "llvm/Support/Error.h"
81
 
82
namespace llvm {
83
 
84
class raw_pwrite_stream;
85
 
86
struct TimeTraceProfiler;
87
TimeTraceProfiler *getTimeTraceProfilerInstance();
88
 
89
/// Initialize the time trace profiler.
90
/// This sets up the global \p TimeTraceProfilerInstance
91
/// variable to be the profiler instance.
92
void timeTraceProfilerInitialize(unsigned TimeTraceGranularity,
93
                                 StringRef ProcName);
94
 
95
/// Cleanup the time trace profiler, if it was initialized.
96
void timeTraceProfilerCleanup();
97
 
98
/// Finish a time trace profiler running on a worker thread.
99
void timeTraceProfilerFinishThread();
100
 
101
/// Is the time trace profiler enabled, i.e. initialized?
102
inline bool timeTraceProfilerEnabled() {
103
  return getTimeTraceProfilerInstance() != nullptr;
104
}
105
 
106
/// Write profiling data to output stream.
107
/// Data produced is JSON, in Chrome "Trace Event" format, see
108
/// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview
109
void timeTraceProfilerWrite(raw_pwrite_stream &OS);
110
 
111
/// Write profiling data to a file.
112
/// The function will write to \p PreferredFileName if provided, if not
113
/// then will write to \p FallbackFileName appending .time-trace.
114
/// Returns a StringError indicating a failure if the function is
115
/// unable to open the file for writing.
116
Error timeTraceProfilerWrite(StringRef PreferredFileName,
117
                             StringRef FallbackFileName);
118
 
119
/// Manually begin a time section, with the given \p Name and \p Detail.
120
/// Profiler copies the string data, so the pointers can be given into
121
/// temporaries. Time sections can be hierarchical; every Begin must have a
122
/// matching End pair but they can nest.
123
void timeTraceProfilerBegin(StringRef Name, StringRef Detail);
124
void timeTraceProfilerBegin(StringRef Name,
125
                            llvm::function_ref<std::string()> Detail);
126
 
127
/// Manually end the last time section.
128
void timeTraceProfilerEnd();
129
 
130
/// The TimeTraceScope is a helper class to call the begin and end functions
131
/// of the time trace profiler.  When the object is constructed, it begins
132
/// the section; and when it is destroyed, it stops it. If the time profiler
133
/// is not initialized, the overhead is a single branch.
134
struct TimeTraceScope {
135
 
136
  TimeTraceScope() = delete;
137
  TimeTraceScope(const TimeTraceScope &) = delete;
138
  TimeTraceScope &operator=(const TimeTraceScope &) = delete;
139
  TimeTraceScope(TimeTraceScope &&) = delete;
140
  TimeTraceScope &operator=(TimeTraceScope &&) = delete;
141
 
142
  TimeTraceScope(StringRef Name) {
143
    if (getTimeTraceProfilerInstance() != nullptr)
144
      timeTraceProfilerBegin(Name, StringRef(""));
145
  }
146
  TimeTraceScope(StringRef Name, StringRef Detail) {
147
    if (getTimeTraceProfilerInstance() != nullptr)
148
      timeTraceProfilerBegin(Name, Detail);
149
  }
150
  TimeTraceScope(StringRef Name, llvm::function_ref<std::string()> Detail) {
151
    if (getTimeTraceProfilerInstance() != nullptr)
152
      timeTraceProfilerBegin(Name, Detail);
153
  }
154
  ~TimeTraceScope() {
155
    if (getTimeTraceProfilerInstance() != nullptr)
156
      timeTraceProfilerEnd();
157
  }
158
};
159
 
160
} // end namespace llvm
161
 
162
#endif