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