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