HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
trace.h
Go to the documentation of this file.
1 //
2 // Copyright 2018 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 
8 #ifndef PXR_BASE_TRACE_TRACE_H
9 #define PXR_BASE_TRACE_TRACE_H
10 
11 /// \file trace/trace.h
12 
13 #include "pxr/pxr.h"
14 
15 #include "pxr/base/trace/api.h"
17 
19 
20 #include <atomic>
21 
22 #if !defined(TRACE_DISABLE)
23 
24 /// Records a timestamp when constructed and a timespan event when destructed,
25 /// using the name of the function or method as the key.
26 #define TRACE_FUNCTION() \
27  _TRACE_FUNCTION_INSTANCE(__LINE__, __ARCH_FUNCTION__, __ARCH_PRETTY_FUNCTION__)
28 
29 /// Records a timestamp when constructed and a timespan event when destructed,
30 /// using \a name as the key.
31 #define TRACE_SCOPE(name) \
32  _TRACE_SCOPE_INSTANCE(__LINE__, name)
33 
34 /// Records a timestamp when constructed and a timespan event when destructed,
35 /// using the name of the function concatenated with \a name as the key.
36 #define TRACE_FUNCTION_SCOPE(name) \
37  _TRACE_FUNCTION_SCOPE_INSTANCE( \
38  __LINE__, __ARCH_FUNCTION__, __ARCH_PRETTY_FUNCTION__, name)
39 
40 /// Records a timestamp when constructed, using \a name as the key.
41 #define TRACE_MARKER(name) \
42  _TRACE_MARKER_INSTANCE(__LINE__, name)
43 
44 /// Records a timestamp when constructed, using \a name as the key.
45 #define TRACE_MARKER_DYNAMIC(name) \
46  _TRACE_MARKER_DYNAMIC_INSTANCE(__LINE__, name)
47 
48 /// Records a counter \a delta using the \a name as the counter key. The delta can
49 /// be positive or negative. A positive delta will increment the total counter
50 /// value, whereas a negative delta will decrement it. The recorded value will
51 /// be stored at the currently traced scope, and will propagate up to the
52 /// parent scopes.
53 #define TRACE_COUNTER_DELTA(name, delta) \
54  _TRACE_COUNTER_INSTANCE(__LINE__, name, delta, /* isDelta */ true)
55 
56 /// Records a counter delta using the name as the counter key. Similar to
57 /// TRACE_COUNTER_DELTA except that \p name does not need to be a compile time
58 /// string.
59 /// \sa TRACE_COUNTER_DELTA
60 #define TRACE_COUNTER_DELTA_DYNAMIC(name, delta) \
61  TraceCollector::GetInstance().RecordCounterDelta(name, delta);
62 
63 /// Records a counter value using the name as the counter key. The recorded
64 /// value will be stored at the currently traced scope, and will propagate up to
65 /// the parent scopes.
66 #define TRACE_COUNTER_VALUE(name, value) \
67  _TRACE_COUNTER_INSTANCE(__LINE__, name, value, /* isDelta */ false)
68 
69 /// Records a counter value using the name as the counter key. Similar to
70 /// TRACE_COUNTER_VALUE except that \p name does not need to be a compile time
71 /// string.
72 /// \sa TRACE_COUNTER_VALUE
73 #define TRACE_COUNTER_VALUE_DYNAMIC(name, value) \
74  TraceCollector::GetInstance().RecordCounterValue(name, value);
75 
76 /// Records a counter value using the name as the counter key. The value can
77 /// be positive or negative. A positive value will increment the total counter
78 /// value, whereas a negative value will decrement it. The recorded value will
79 /// be stored at the currently traced scope, and will propagate up to the
80 /// parent scopes.
81 ///
82 /// This macro provides the same functionality as TRACE_COUNTER_DELTA, but takes
83 /// a section of code in brackets, which assumes that a value will be
84 /// assigned to 'value'. The section of code will not be executed, when
85 /// tracing is turned off, which makes it possible to gather counter values
86 /// from potentially expensive logic, without incurring an overhead with
87 /// tracing turned off.
88 ///
89 /// Usage:
90 ///
91 /// TRACE_COUNTER_DELTA_CODE("My counter", {
92 /// value = _ComputeExpensiveCounterValue();
93 /// })
94 #define TRACE_COUNTER_DELTA_CODE(name, code) \
95  _TRACE_COUNTER_CODE_INSTANCE(__LINE__, name, code, true)
96 
97 /// Records a begin event when constructed and an end event when destructed,
98 /// using name of the function or method and the supplied name as the key.
99 /// Unlike TRACE_FUNCTION, the name argument will be evaluated each time this
100 /// macro is invoked. This allows for a single TRACE_FUNCTION to track time
101 /// under different keys, but incurs greater overhead.
102 #define TRACE_FUNCTION_DYNAMIC(name) \
103  _TRACE_FUNCTION_DYNAMIC_INSTANCE(__LINE__, __ARCH_FUNCTION__, __ARCH_PRETTY_FUNCTION__, name)
104 
105 /// Records a begin event when constructed and an end event when destructed,
106 /// using \a name as the key. Unlike TRACE_SCOPE, the name argument will
107 /// be evaluated each time this macro is invoked. This allows for a single
108 /// TRACE_SCOPE to track time under different keys, but incurs greater
109 /// overhead.
110 #define TRACE_SCOPE_DYNAMIC(name) \
111  _TRACE_SCOPE_DYNAMIC_INSTANCE(__LINE__, name)
112 
113 
114 /// These pair a uniquely named TraceScopeHolder with a TraceScopeAuto.
115 /// Together these will register a TraceScope only the first time the
116 /// code is executed or if the TraceScope expires. Otherwise, the held
117 /// TraceScope will be used to record begin and end events.
118 
119 
120 #define _TRACE_FUNCTION_INSTANCE(instance, name, prettyName) \
121 constexpr static PXR_NS::TraceStaticKeyData \
122  TF_PP_CAT(TraceKeyData_, instance)(name, prettyName); \
123 PXR_NS::TraceScopeAuto TF_PP_CAT(TraceScopeAuto_, instance)(\
124  TF_PP_CAT(TraceKeyData_, instance));
125 
126 #define _TRACE_SCOPE_INSTANCE(instance, name) \
127 constexpr static PXR_NS::TraceStaticKeyData \
128  TF_PP_CAT(TraceKeyData_, instance)(name); \
129 PXR_NS::TraceScopeAuto TF_PP_CAT(TraceScopeAuto_, instance)(\
130  TF_PP_CAT(TraceKeyData_, instance));
131 
132 #define _TRACE_FUNCTION_SCOPE_INSTANCE(instance, name, prettyName, scopeName) \
133 constexpr static PXR_NS::TraceStaticKeyData \
134  TF_PP_CAT(TraceKeyData_, instance)(name, prettyName, scopeName); \
135 PXR_NS::TraceScopeAuto TF_PP_CAT(TraceScopeAuto_, instance)(\
136  TF_PP_CAT(TraceKeyData_, instance));
137 
138 #define _TRACE_MARKER_INSTANCE(instance, name) \
139 constexpr static PXR_NS::TraceStaticKeyData \
140  TF_PP_CAT(TraceKeyData_, instance)(name); \
141  TraceCollector::GetInstance().MarkerEventStatic(TF_PP_CAT(TraceKeyData_, instance));
142 
143 #define _TRACE_COUNTER_INSTANCE(instance, name, value, isDelta) \
144 constexpr static PXR_NS::TraceStaticKeyData \
145  TF_PP_CAT(TraceKeyData_, instance)(name); \
146 static PXR_NS::TraceCounterHolder \
147  TF_PP_CAT(TraceCounterHolder_, instance) \
148  (TF_PP_CAT(TraceKeyData_, instance)); \
149 TF_PP_CAT(TraceCounterHolder_, instance).Record(value, isDelta);
150 
151 #define _TRACE_COUNTER_CODE_INSTANCE(instance, name, code, isDelta) \
152 static PXR_NS::TraceCounterHolder \
153  TF_PP_CAT(TraceCounterHolder_, instance)(name); \
154 if (TF_PP_CAT(TraceCounterHolder_, instance).IsEnabled()) { \
155  double value = 0.0; \
156  code \
157  TF_PP_CAT(TraceCounterHolder_, instance).RecordDelta(value, isDelta); \
158 }
159 
160 #define _TRACE_FUNCTION_DYNAMIC_INSTANCE(instance, fnName, fnPrettyName, name) \
161 PXR_NS::TraceAuto TF_PP_CAT(TraceAuto_, instance)(fnName, fnPrettyName, name)
162 
163 #define _TRACE_SCOPE_DYNAMIC_INSTANCE(instance, str) \
164 PXR_NS::TraceAuto TF_PP_CAT(TraceAuto_, instance)(str)
165 
166 #define _TRACE_MARKER_DYNAMIC_INSTANCE(instance, name) \
167  TraceCollector::GetInstance().MarkerEvent(name);
168 
169 #else // TRACE_DISABLE
170 
171 #define TRACE_FUNCTION()
172 #define TRACE_FUNCTION_DYNAMIC(name)
173 #define TRACE_SCOPE(name)
174 #define TRACE_SCOPE_DYNAMIC(name)
175 #define TRACE_FUNCTION_SCOPE(name)
176 #define TRACE_MARKER(name)
177 #define TRACE_MARKER_DYNAMIC(name)
178 
179 #endif // TRACE_DISABLE
180 
182 
183 ////////////////////////////////////////////////////////////////////////////////
184 /// \class TraceScopeAuto
185 ///
186 /// A class which records a timestamp when it is created and a
187 /// scope event when it is destructed.
188 ///
190 public:
191  /// Constructor for TRACE_FUNCTION macro.
192  ///
193  explicit TraceScopeAuto(const TraceStaticKeyData& key) noexcept
194  : _key(&key)
195  , _intervalTimer(/*start=*/TraceCollector::IsEnabled()) {
196  }
197 
198  /// Constructor that also records scope arguments.
199  ///
200  template < typename... Args>
201  TraceScopeAuto(const TraceStaticKeyData& key, Args&&... args)
202  : _key(&key)
203  , _intervalTimer(/*start=*/false) {
205  _intervalTimer.Start();
207  ::GetInstance().ScopeArgs(std::forward<Args>(args)...);
208  }
209  }
210 
211  /// Destructor.
212  ///
213  ~TraceScopeAuto() noexcept {
214  if (_intervalTimer.IsStarted()) {
215  TraceCollector::TimeStamp stopTicks =
216  _intervalTimer.GetCurrentTicks();
218  *_key, _intervalTimer.GetStartTicks(), stopTicks);
219  }
220  }
221 
222 private:
223  const TraceStaticKeyData* const _key;
224  ArchIntervalTimer _intervalTimer;
225 };
226 
227 ////////////////////////////////////////////////////////////////////////////////
228 /// \class TraceAuto
229 ///
230 /// A class which records a begin event when it is constructed, and a matching
231 /// end event when it is destructed. It is intended to help ensure begin-end
232 /// pairing correctness when the begin-end pairing can be expressed by automatic
233 /// variable lifetime.
234 ///
235 /// The TRACE_FUNCTION() macro may be even more convenient in some
236 /// circumstances.
237 ///
238 struct TraceAuto {
239  /// Constructor taking function name, pretty function name and a scope name.
240  ///
241  TraceAuto(const char *funcName, const char *prettyFuncName,
242  const std::string &name)
243  : _key(_CreateKeyString(funcName, prettyFuncName, name)) {
244  std::atomic_thread_fence(std::memory_order_seq_cst);
245  _collector = &TraceCollector::GetInstance();
246  _collector->BeginEvent(_key);
247  std::atomic_thread_fence(std::memory_order_seq_cst);
248  }
249 
250  /// Constructor taking a TfToken key.
251  ///
252  explicit TraceAuto(const TfToken& key)
253  : _key(key) {
254  std::atomic_thread_fence(std::memory_order_seq_cst);
255  _collector = &TraceCollector::GetInstance();
256  _collector->BeginEvent(_key);
257  std::atomic_thread_fence(std::memory_order_seq_cst);
258  }
259 
260  /// Constructor taking a string key.
261  ///
262  explicit TraceAuto(const std::string& key)
263  : TraceAuto(TfToken(key)) {}
264 
265  // Non-copyable
266  //
267  TraceAuto(const TraceAuto &) = delete;
268  TraceAuto& operator=(const TraceAuto &) = delete;
269 
270  // Non-movable
271  //
272  TraceAuto(TraceAuto &&) = delete;
273  TraceAuto& operator=(TraceAuto &&) = delete;
274 
275  /// Destructor.
276  ///
278  std::atomic_thread_fence(std::memory_order_seq_cst);
279  _collector->EndEvent(_key);
280  std::atomic_thread_fence(std::memory_order_seq_cst);
281  }
282 
283 private:
284  static std::string _CreateKeyString(
285  const char *funcName,
286  const char *prettyFuncName,
287  const std::string &name) {
288  std::string key = ArchGetPrettierFunctionName(funcName, prettyFuncName);
289  key += " [";
290  key += name;
291  key += "]";
292  return key;
293  }
294 
295  TraceCollector* _collector;
296  TraceDynamicKey _key;
297 };
298 
299 ////////////////////////////////////////////////////////////////////////////////
300 /// \class TraceCounterHolder
301 ///
302 /// Holds on to a counter key, as well as the global
303 /// collector for fast lookup.
304 ///
306 public:
307  /// Constructor used by TRACE_COUNTER_* macro.
308  ///
309  explicit TraceCounterHolder(const TraceKey& key)
310  : _key(key) {}
311 
312  /// Returns whether the TraceCollector is enabled or not.
313  ///
314  bool IsEnabled() const {
315  return TraceCollector::IsEnabled();
316  }
317 
318  /// Records a counter delta \p value if the TraceCollector is enabled.
319  ///
320  void Record(double value, bool delta) {
321  if (delta) {
323  } else {
325  }
326  }
327 
328 private:
329  TraceKey _key;
330 };
331 
333 
334 #endif // PXR_BASE_TRACE_TRACE_H
static TRACE_API TraceCollector & GetInstance()
Returns the singleton instance.
Definition: collector.h:67
void RecordCounterValue(const TraceKey &key, double value)
Record a counter value for a name key if Category is enabled.
Definition: collector.h:358
~TraceScopeAuto() noexcept
Definition: trace.h:213
GLsizei const GLfloat * value
Definition: glcorearb.h:824
bool IsStarted() const
Definition: timing.h:232
TraceAuto(const char *funcName, const char *prettyFuncName, const std::string &name)
Definition: trace.h:241
TraceAuto(const TfToken &key)
Definition: trace.h:252
void ScopeArgs(Args &&...args)
Definition: collector.h:282
bool IsEnabled() const
Definition: trace.h:314
~TraceAuto()
Definition: trace.h:277
Definition: token.h:70
static bool IsEnabled()
Returns whether collection of events is enabled for DefaultCategory.
Definition: collector.h:77
uint64_t GetCurrentTicks()
Definition: timing.h:240
TraceAuto & operator=(const TraceAuto &)=delete
uint64_t GetStartTicks() const
Definition: timing.h:236
GLuint const GLchar * name
Definition: glcorearb.h:786
void Record(double value, bool delta)
Definition: trace.h:320
TimeStamp EndEvent(const Key &key)
Definition: collector.h:148
void Start()
Definition: timing.h:227
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
TimeStamp BeginEvent(const Key &key)
Definition: collector.h:119
static TRACE_API void Scope(const TraceKey &key, TimeStamp start, TimeStamp stop) noexcept
**If you just want to fire and args
Definition: thread.h:618
TraceCounterHolder(const TraceKey &key)
Definition: trace.h:309
TraceAuto(const std::string &key)
Definition: trace.h:262
TraceScopeAuto(const TraceStaticKeyData &key) noexcept
Definition: trace.h:193
PXR_NAMESPACE_OPEN_SCOPE ARCH_API std::string ArchGetPrettierFunctionName(const std::string &function, const std::string &prettyFunction)
TraceScopeAuto(const TraceStaticKeyData &key, Args &&...args)
Definition: trace.h:201
TraceEvent::TimeStamp TimeStamp
Definition: collector.h:62
void RecordCounterDelta(const TraceKey &key, double delta)
Record a counter delta for a name key if Category is enabled.
Definition: collector.h:337
Definition: key.h:23