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)
211  : _key(nullptr)
212  , _start(0) {
213 
215  // Init the key if needed.
216  _key = &key;
217  _start = ArchGetTickTime();
218  }
219 
220  }
221 
222  /// Constructor that also records scope arguments.
223  ///
224  template < typename... Args>
225  TraceScopeAuto(const TraceStaticKeyData& key, Args&&... args)
226  : TraceScopeAuto(key) {
227  if (ARCH_UNLIKELY(_key)) {
228  TraceCollector::GetInstance().ScopeArgs(std::forward<Args>(args)...);
229  }
230  }
231 
232  /// Destructor.
233  ///
235  if (ARCH_UNLIKELY(_key)) {
236  TraceCollector::GetInstance().Scope(*_key, _start);
237  }
238  }
239 
240 private:
241  const TraceStaticKeyData* _key;
242  TraceEvent::TimeStamp _start;
243 };
244 
245 ////////////////////////////////////////////////////////////////////////////////
246 /// \class TraceAuto
247 ///
248 /// A class which records a begin event when it is constructed, and a matching
249 /// end event when it is destructed. It is intended to help ensure begin-end
250 /// pairing correctness when the begin-end pairing can be expressed by automatic
251 /// variable lifetime.
252 ///
253 /// The TRACE_FUNCTION() macro may be even more convenient in some
254 /// circumstances.
255 ///
256 struct TraceAuto {
257  /// Constructor taking function name, pretty function name and a scope name.
258  ///
259  TraceAuto(const char *funcName, const char *prettyFuncName,
260  const std::string &name)
261  : _key(_CreateKeyString(funcName, prettyFuncName, name)) {
262  std::atomic_thread_fence(std::memory_order_seq_cst);
263  _collector = &TraceCollector::GetInstance();
264  _collector->BeginEvent(_key);
265  std::atomic_thread_fence(std::memory_order_seq_cst);
266  }
267 
268  /// Constructor taking a TfToken key.
269  ///
270  explicit TraceAuto(const TfToken& key)
271  : _key(key) {
272  std::atomic_thread_fence(std::memory_order_seq_cst);
273  _collector = &TraceCollector::GetInstance();
274  _collector->BeginEvent(_key);
275  std::atomic_thread_fence(std::memory_order_seq_cst);
276  }
277 
278  /// Constructor taking a string key.
279  ///
280  explicit TraceAuto(const std::string& key)
281  : TraceAuto(TfToken(key)) {}
282 
283  // Non-copyable
284  //
285  TraceAuto(const TraceAuto &) = delete;
286  TraceAuto& operator=(const TraceAuto &) = delete;
287 
288  // Non-movable
289  //
290  TraceAuto(TraceAuto &&) = delete;
291  TraceAuto& operator=(TraceAuto &&) = delete;
292 
293  /// Destructor.
294  ///
296  std::atomic_thread_fence(std::memory_order_seq_cst);
297  _collector->EndEvent(_key);
298  std::atomic_thread_fence(std::memory_order_seq_cst);
299  }
300 
301 private:
302  static std::string _CreateKeyString(
303  const char *funcName,
304  const char *prettyFuncName,
305  const std::string &name) {
306  std::string key = ArchGetPrettierFunctionName(funcName, prettyFuncName);
307  key += " [";
308  key += name;
309  key += "]";
310  return key;
311  }
312 
313  TraceCollector* _collector;
314  TraceDynamicKey _key;
315 };
316 
317 ////////////////////////////////////////////////////////////////////////////////
318 /// \class TraceCounterHolder
319 ///
320 /// Holds on to a counter key, as well as the global
321 /// collector for fast lookup.
322 ///
324 public:
325  /// Constructor used by TRACE_COUNTER_* macro.
326  ///
327  explicit TraceCounterHolder(const TraceKey& key)
328  : _key(key) {}
329 
330  /// Returns whether the TraceCollector is enabled or not.
331  ///
332  bool IsEnabled() const {
333  return TraceCollector::IsEnabled();
334  }
335 
336  /// Records a counter delta \p value if the TraceCollector is enabled.
337  ///
338  void Record(double value, bool delta) {
339  if (delta) {
341  } else {
343  }
344  }
345 
346 private:
347  TraceKey _key;
348 };
349 
351 
352 #endif // PXR_BASE_TRACE_TRACE_H
static TRACE_API TraceCollector & GetInstance()
Returns the singleton instance.
Definition: collector.h:84
void Scope(const TraceKey &key, TimeStamp start)
Definition: collector.h:274
void RecordCounterValue(const TraceKey &key, double value)
Record a counter value for a name key if Category is enabled.
Definition: collector.h:363
PXR_NAMESPACE_OPEN_SCOPE ARCH_API std::string ArchGetPrettierFunctionName(const std::string &function, const std::string &prettyFunction)
uint64_t ArchGetTickTime()
Definition: timing.h:64
~TraceScopeAuto()
Definition: trace.h:234
TraceAuto(const char *funcName, const char *prettyFuncName, const std::string &name)
Definition: trace.h:259
TraceAuto(const TfToken &key)
Definition: trace.h:270
GLuint const GLchar * name
Definition: glcorearb.h:785
void ScopeArgs(Args &&...args)
Definition: collector.h:287
bool IsEnabled() const
Definition: trace.h:332
~TraceAuto()
Definition: trace.h:295
#define ARCH_UNLIKELY(x)
Definition: hints.h:47
Definition: token.h:87
static bool IsEnabled()
Returns whether collection of events is enabled for DefaultCategory.
Definition: collector.h:94
GLsizei const GLchar *const * string
Definition: glcorearb.h:813
TraceAuto & operator=(const TraceAuto &)=delete
void Record(double value, bool delta)
Definition: trace.h:338
TimeStamp EndEvent(const Key &key)
Definition: collector.h:162
TraceScopeAuto(const TraceStaticKeyData &key)
Definition: trace.h:210
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1375
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
TimeStamp BeginEvent(const Key &key)
Definition: collector.h:133
GLsizei const GLfloat * value
Definition: glcorearb.h:823
uint64_t TimeStamp
Time in "ticks".
Definition: event.h:50
**If you just want to fire and args
Definition: thread.h:615
TraceCounterHolder(const TraceKey &key)
Definition: trace.h:327
TraceAuto(const std::string &key)
Definition: trace.h:280
TraceScopeAuto(const TraceStaticKeyData &key, Args &&...args)
Definition: trace.h:225
void RecordCounterDelta(const TraceKey &key, double delta)
Record a counter delta for a name key if Category is enabled.
Definition: collector.h:342
Definition: key.h:40