All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
collector.h
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 TRACE_COLLECTOR_H
26 #define TRACE_COLLECTOR_H
27 
28 #include "pxr/pxr.h"
29 
30 #include "pxr/base/trace/api.h"
31 #include "pxr/base/trace/concurrentList.h"
32 #include "pxr/base/trace/collection.h"
33 #include "pxr/base/trace/event.h"
34 #include "pxr/base/trace/key.h"
35 #include "pxr/base/trace/threads.h"
36 
37 #include "pxr/base/tf/declarePtrs.h"
38 #include "pxr/base/tf/mallocTag.h"
39 
40 #ifdef PXR_PYTHON_SUPPORT_ENABLED
41 #include "pxr/base/tf/pyTracing.h"
42 #endif // PXR_PYTHON_SUPPORT_ENABLED
43 
44 #include "pxr/base/tf/singleton.h"
45 #include "pxr/base/tf/refBase.h"
46 #include "pxr/base/tf/refPtr.h"
47 #include "pxr/base/tf/weakBase.h"
48 #include "pxr/base/tf/weakPtr.h"
49 
50 #include <atomic>
51 #include <string>
52 #include <vector>
53 
54 #include <tbb/spin_mutex.h>
55 
56 PXR_NAMESPACE_OPEN_SCOPE
57 
58 class TraceScopeHolder;
59 
62 
63 
71 class TraceCollector : public TfWeakBase {
72 public:
73 
74  TF_MALLOC_TAG_NEW("Trace", "TraceCollector");
75 
76  using This = TraceCollector;
77  using ThisPtr = TraceCollectorPtr;
78 
79  using TimeStamp = TraceEvent::TimeStamp;
80 
81  using Key = TraceDynamicKey;
82 
84  TRACE_API static TraceCollector& GetInstance() {
86  }
87 
88  TRACE_API ~TraceCollector();
89 
91  TRACE_API void SetEnabled(bool isEnabled);
92 
94  static bool IsEnabled() {
95  return (_isEnabled.load(std::memory_order_acquire) == 1);
96  }
97 
102  static constexpr TraceCategoryId GetId() { return TraceCategory::Default;}
104  static bool IsEnabled() { return TraceCollector::IsEnabled(); }
105  };
106 
107 #ifdef PXR_PYTHON_SUPPORT_ENABLED
108  bool IsPythonTracingEnabled() const {
110  return _isPythonTracingEnabled.load(std::memory_order_acquire) != 0;
111  }
112 
114  TRACE_API void SetPythonTracingEnabled(bool enabled);
115 #endif // PXR_PYTHON_SUPPORT_ENABLED
116 
119  TRACE_API void Clear();
120 
123 
132  template <typename Category = DefaultCategory>
133  TimeStamp BeginEvent(const Key& key) {
134  if (ARCH_LIKELY(!Category::IsEnabled())) {
135  return 0;
136  }
137  return _BeginEvent(key, Category::GetId());
138  }
139 
145  template <typename Category = DefaultCategory>
146  void BeginEventAtTime(const Key& key, double ms) {
147  if (ARCH_LIKELY(!Category::IsEnabled())) {
148  return;
149  }
150  _BeginEventAtTime(key, ms, Category::GetId());
151  }
152 
161  template <typename Category = DefaultCategory>
162  TimeStamp EndEvent(const Key& key) {
163  if (ARCH_LIKELY(!Category::IsEnabled())) {
164  return 0;
165  }
166  return _EndEvent(key, Category::GetId());
167  }
168 
174  template <typename Category = DefaultCategory>
175  void EndEventAtTime(const Key& key, double ms) {
176  if (ARCH_LIKELY(!Category::IsEnabled())) {
177  return;
178  }
179  _EndEventAtTime(key, ms, Category::GetId());
180  }
181 
182 
186 
187  template <typename Category = DefaultCategory>
188  TimeStamp MarkerEvent(const Key& key) {
189  if (ARCH_LIKELY(!Category::IsEnabled())) {
190  return 0;
191  }
192  return _MarkerEvent(key, Category::GetId());
193  }
194 
200  template <typename Category = DefaultCategory>
201  void MarkerEventAtTime(const Key& key, double ms) {
202  if (ARCH_LIKELY(!Category::IsEnabled())) {
203  return;
204  }
205  _MarkerEventAtTime(key, ms, Category::GetId());
206  }
207 
213  template <typename Category = DefaultCategory>
214  void BeginScope(const TraceKey& _key) {
215  if (ARCH_LIKELY(!Category::IsEnabled()))
216  return;
217 
218  _BeginScope(_key, Category::GetId());
219  }
220 
226  template <typename Category, typename... Args>
228  const TraceKey& key, Args&&... args) {
229  static_assert( sizeof...(Args) %2 == 0,
230  "Data arguments must come in pairs");
231 
232  if (ARCH_LIKELY(!Category::IsEnabled()))
233  return;
234 
235  _PerThreadData *threadData = _GetThreadData();
236  threadData->BeginScope(key, Category::GetId());
237  _StoreDataRec(threadData, Category::GetId(), std::forward<Args>(args)...);
238  }
239 
244  template <typename... Args>
245  void BeginScope(const TraceKey& key, Args&&... args) {
246  static_assert( sizeof...(Args) %2 == 0,
247  "Data arguments must come in pairs");
248 
249  // Explicitly cast to TraceCategoryId so overload resolution choose the
250  // version with a category arguement.
251  BeginScope<DefaultCategory>(key,
252  std::forward<Args>(args)...);
253  }
254 
259  template <typename Category = DefaultCategory>
260  void EndScope(const TraceKey& key) {
261  if (ARCH_LIKELY(!Category::IsEnabled()))
262  return;
263 
264  _EndScope(key, Category::GetId());
265  }
266 
273  template <typename Category = DefaultCategory>
274  void Scope(const TraceKey& key, TimeStamp start) {
275  if (ARCH_LIKELY(!Category::IsEnabled()))
276  return;
277 
278  _PerThreadData *threadData = _GetThreadData();
279  threadData->EmplaceEvent(
280  TraceEvent::Timespan, key, start, Category::GetId());
281  }
282 
286  template <typename Category, typename... Args>
287  void ScopeArgs(Args&&... args) {
288  static_assert( sizeof...(Args) %2 == 0,
289  "Data arguments must come in pairs");
290 
291  if (ARCH_LIKELY(!Category::IsEnabled()))
292  return;
293 
294  _PerThreadData *threadData = _GetThreadData();
295  _StoreDataRec(threadData, Category::GetId(), std::forward<Args>(args)...);
296  }
297 
304  template <typename... Args>
305  void ScopeArgs(Args&&... args) {
306  static_assert( sizeof...(Args) %2 == 0,
307  "Data arguments must come in pairs");
308 
309  ScopeArgs<DefaultCategory>(std::forward<Args>(args)...);
310  }
311 
312 
319  template <typename Category = DefaultCategory>
320  void MarkerEventStatic(const TraceKey& key) {
321  if (ARCH_LIKELY(!Category::IsEnabled()))
322  return;
323 
324  _PerThreadData *threadData = _GetThreadData();
325  threadData->EmplaceEvent(
326  TraceEvent::Marker, key, Category::GetId());
327  }
328 
333  template <typename Category = DefaultCategory, typename T>
334  void StoreData(const TraceKey &key, const T& value) {
335  if (ARCH_UNLIKELY(Category::IsEnabled())) {
336  _StoreData(_GetThreadData(), key, Category::GetId(), value);
337  }
338  }
339 
341  template <typename Category = DefaultCategory>
342  void RecordCounterDelta(const TraceKey &key,
343  double delta) {
344  // Only record counter values if the collector is enabled.
345  if (ARCH_UNLIKELY(Category::IsEnabled())) {
346  _PerThreadData *threadData = _GetThreadData();
347  threadData->EmplaceEvent(
348  TraceEvent::CounterDelta, key, delta, Category::GetId());
349  }
350  }
351 
353  template <typename Category = DefaultCategory>
354  void RecordCounterDelta(const Key &key, double delta) {
355  if (ARCH_UNLIKELY(Category::IsEnabled())) {
356  _PerThreadData *threadData = _GetThreadData();
357  threadData->CounterDelta(key, delta, Category::GetId());
358  }
359  }
360 
362  template <typename Category = DefaultCategory>
363  void RecordCounterValue(const TraceKey &key, double value) {
364  // Only record counter values if the collector is enabled.
365  if (ARCH_UNLIKELY(Category::IsEnabled())) {
366  _PerThreadData *threadData = _GetThreadData();
367  threadData->EmplaceEvent(
368  TraceEvent::CounterValue, key, value, Category::GetId());
369  }
370  }
371 
374  template <typename Category = DefaultCategory>
375  void RecordCounterValue(const Key &key, double value) {
376 
377  if (ARCH_UNLIKELY(Category::IsEnabled())) {
378  _PerThreadData *threadData = _GetThreadData();
379  threadData->CounterValue(key, value, Category::GetId());
380  }
381  }
382 
384 
386  const std::string& GetLabel() {
387  return _label;
388  }
389 
394  TRACE_API void CreateCollection();
395 
396 private:
397 
398  TraceCollector();
399 
400  friend class TfSingleton<TraceCollector>;
401 
402  class _PerThreadData;
403 
404  // Return a pointer to existing per-thread data or create one if none
405  // exists.
406  TRACE_API _PerThreadData* _GetThreadData();
407 
408  TRACE_API TimeStamp _BeginEvent(const Key& key, TraceCategoryId cat);
409 
410  TRACE_API void _BeginEventAtTime(
411  const Key& key, double ms, TraceCategoryId cat);
412 
413  TRACE_API TimeStamp _EndEvent(const Key& key, TraceCategoryId cat);
414 
415  TRACE_API void _EndEventAtTime(
416  const Key& key, double ms, TraceCategoryId cat);
417 
418  TRACE_API TimeStamp _MarkerEvent(const Key& key, TraceCategoryId cat);
419 
420  TRACE_API void _MarkerEventAtTime(
421  const Key& key, double ms, TraceCategoryId cat);
422 
423  // This is the fast execution path called from the TRACE_FUNCTION
424  // and TRACE_SCOPE macros
425  void _BeginScope(const TraceKey& key, TraceCategoryId cat)
426  {
427  // Note we're not calling _NewEvent, don't need to cache key
428  _PerThreadData *threadData = _GetThreadData();
429  threadData->BeginScope(key, cat);
430  }
431 
432  // This is the fast execution path called from the TRACE_FUNCTION
433  // and TRACE_SCOPE macros
434  TRACE_API void _EndScope(const TraceKey& key, TraceCategoryId cat);
435 
436 #ifdef PXR_PYTHON_SUPPORT_ENABLED
437  // Callback function registered as a python tracing function.
438  void _PyTracingCallback(const TfPyTraceInfo &info);
439 #endif // PXR_PYTHON_SUPPORT_ENABLED
440 
441  // Implementation for small data that can stored inlined with the event.
442  template <typename T,
443  typename std::enable_if<
444  sizeof(T) <= sizeof(uintptr_t)
445  && !std::is_pointer<T>::value , int>::type = 0>
446  void _StoreData(_PerThreadData* threadData, const TraceKey &key,
447  TraceCategoryId cat, const T& value) {
448  threadData->StoreData(key, value, cat);
449  }
450 
451  // Implementation for data that must be stored outside of the events.
452  template <typename T,
453  typename std::enable_if<
454  (sizeof(T) > sizeof(uintptr_t))
455  && !std::is_pointer<T>::value, int>::type = 0>
456  void _StoreData(_PerThreadData* threadData, const TraceKey &key,
457  TraceCategoryId cat, const T& value) {
458  threadData->StoreLargeData(key, value, cat);
459  }
460 
461  // Specialization for c string
462  void _StoreData(
463  _PerThreadData* threadData,
464  const TraceKey &key,
465  TraceCategoryId cat,
466  const char* value) {
467  threadData->StoreLargeData(key, value, cat);
468  }
469 
470  // Specialization for std::string
471  void _StoreData(
472  _PerThreadData* threadData,
473  const TraceKey &key,
474  TraceCategoryId cat,
475  const std::string& value) {
476  threadData->StoreLargeData(key, value.c_str(), cat);
477  }
478 
479  // Variadic version to store multiple data events in one function call.
480  template <typename K, typename T, typename... Args>
481  void _StoreDataRec(
482  _PerThreadData* threadData, TraceCategoryId cat, K&& key,
483  const T& value, Args&&... args) {
484  _StoreData(threadData, std::forward<K>(key), cat, value);
485  _StoreDataRec(threadData, cat, std::forward<Args>(args)...);
486  }
487 
488  // Base case to terminate template recursion
489  void _StoreDataRec(_PerThreadData* threadData, TraceCategoryId cat) {}
490 
491 
492  // Thread-local storage, accessed via _GetThreadData()
493  //
494  class _PerThreadData {
495  public:
496  using EventList = TraceCollection::EventList;
497 
498  _PerThreadData();
499  ~_PerThreadData();
500 
501  const TraceThreadId& GetThreadId() const {
502  return _threadIndex;
503  }
504  TimeStamp BeginEvent(const Key& key, TraceCategoryId cat);
505  TimeStamp EndEvent(const Key& key, TraceCategoryId cat);
506  TimeStamp MarkerEvent(const Key& key, TraceCategoryId cat);
507 
508  // Debug Methods
509  void BeginEventAtTime(
510  const Key& key, double ms, TraceCategoryId cat);
511  void EndEventAtTime(const Key& key, double ms, TraceCategoryId cat);
512  void MarkerEventAtTime(const Key& key, double ms, TraceCategoryId cat);
513 
514  void BeginScope(const TraceKey& key, TraceCategoryId cat) {
515  AtomicRef lock(_writing);
516  _BeginScope(key, cat);
517  }
518 
519  void EndScope(const TraceKey& key, TraceCategoryId cat) {
520  AtomicRef lock(_writing);
521  _EndScope(key, cat);
522  }
523 
524  TRACE_API void CounterDelta(
525  const Key&, double value, TraceCategoryId cat);
526 
527  TRACE_API void CounterValue(
528  const Key&, double value, TraceCategoryId cat);
529 
530  template <typename T>
531  void StoreData(
532  const TraceKey& key, const T& data, TraceCategoryId cat) {
533  AtomicRef lock(_writing);
534  _events.load(std::memory_order_acquire)->EmplaceBack(
535  TraceEvent::Data, key, data, cat);
536  }
537 
538  template <typename T>
539  void StoreLargeData(
540  const TraceKey& key, const T& data, TraceCategoryId cat) {
541  AtomicRef lock(_writing);
542  EventList* events = _events.load(std::memory_order_acquire);
543  const auto* cached = events->StoreData(data);
544  events->EmplaceBack(TraceEvent::Data, key, cached, cat);
545  }
546 
547  template <typename... Args>
548  void EmplaceEvent(Args&&... args) {
549  AtomicRef lock(_writing);
550  _events.load(std::memory_order_acquire)->EmplaceBack(
551  std::forward<Args>(args)...);
552  }
553 
554 #ifdef PXR_PYTHON_SUPPORT_ENABLED
555  void PushPyScope(const Key& key, bool enabled);
556  void PopPyScope(bool enabled);
557 #endif // PXR_PYTHON_SUPPORT_ENABLED
558 
559  // These methods can be called from threads at the same time as the
560  // other methods.
561  std::unique_ptr<EventList> GetCollectionData();
562  void Clear();
563 
564  private:
565  void _BeginScope(const TraceKey& key, TraceCategoryId cat) {
566  _events.load(std::memory_order_acquire)->EmplaceBack(
567  TraceEvent::Begin, key, cat);
568  }
569 
570  void _EndScope(const TraceKey& key, TraceCategoryId cat);
571 
572  // Flag to let other threads know that the list is being written to.
573  mutable std::atomic<bool> _writing;
574  std::atomic<EventList*> _events;
575 
576  class AtomicRef {
577  public:
578  AtomicRef(std::atomic<bool>& b) : _bool(b) {
579  _bool.store(true, std::memory_order_release);
580  }
581  ~AtomicRef() {
582  _bool.store(false, std::memory_order_release);
583  }
584  private:
585  std::atomic<bool>& _bool;
586  };
587 
588  // An integer that is unique for each thread launched by any
589  // threadDispatcher. Each time a thread is Start-ed it get's
590  // a new id.
591  //
592  TraceThreadId _threadIndex;
593 
594 #ifdef PXR_PYTHON_SUPPORT_ENABLED
595  // When auto-tracing python frames, this stores the stack of scopes.
596  struct PyScope {
597  Key key;
598  };
599  std::vector<PyScope> _pyScopes;
600 #endif // PXR_PYTHON_SUPPORT_ENABLED
601  };
602 
603  TRACE_API static std::atomic<int> _isEnabled;
604 
605  // A list with one _PerThreadData per thread.
606  TraceConcurrentList<_PerThreadData> _allPerThreadData;
607 
608  std::string _label;
609 
610 #ifdef PXR_PYTHON_SUPPORT_ENABLED
611  std::atomic<int> _isPythonTracingEnabled;
612  TfPyTraceFnId _pyTraceFnId;
613 #endif // PXR_PYTHON_SUPPORT_ENABLED
614 };
615 
616 TRACE_API_TEMPLATE_CLASS(TfSingleton<TraceCollector>);
617 
618 PXR_NAMESPACE_CLOSE_SCOPE
619 
620 #endif // TRACE_COLLECTOR_H
const std::string & GetLabel()
Return the label associated with this collector.
Definition: collector.h:386
static bool IsEnabled()
Returns the result of TraceCollector::IsEnabled.
Definition: collector.h:104
void StoreData(const TraceKey &key, const T &value)
Record a data event with the given key and value if Category is enabled.
Definition: collector.h:334
TRACE_API void CreateCollection()
Produces a TraceCollection from all the events that recorded in the collector and issues a TraceColle...
TRACE_API void SetEnabled(bool isEnabled)
Enables or disables collection of events for DefaultCategory.
Manage a single instance of an object (see.
Definition: singleton.h:122
void RecordCounterValue(const Key &key, double value)
Record a counter value for a name key and delta value if Category is enabled.
Definition: collector.h:375
void BeginEventAtTime(const Key &key, double ms)
Record a begin event with key at a specified time if Category is enabled.
Definition: collector.h:146
#define TF_DECLARE_WEAK_PTRS(type)
Define standard weak pointer types.
Definition: declarePtrs.h:62
void MarkerEventStatic(const TraceKey &key)
Record a scope event described by key that started at start if Category is enabled.
Definition: collector.h:320
void MarkerEventAtTime(const Key &key, double ms)
Record a marker event with key at a specified time if Category is enabled.
Definition: collector.h:201
TimeStamp EndEvent(const Key &key)
Record an end event with key if Category is enabled.
Definition: collector.h:162
uint64_t TimeStamp
Time in &quot;ticks&quot;.
Definition: event.h:50
void BeginScope(const TraceKey &key, Args &&...args)
Record a begin event for a scope described by key and store data arguments if Category is enabled...
Definition: collector.h:245
void RecordCounterValue(const TraceKey &key, double value)
Record a counter value for a name key if Category is enabled.
Definition: collector.h:363
#define TF_DECLARE_WEAK_AND_REF_PTRS(type)
Define standard weak, ref, and vector pointer types.
Definition: declarePtrs.h:89
static constexpr TraceCategoryId GetId()
Returns TraceCategory::Default.
Definition: collector.h:102
TRACE_API void Clear()
Clear all pending events from the collector.
This class stores data used to create dynamic keys which can be referenced in TraceEvent instances...
Definition: dynamicKey.h:42
TimeStamp BeginEvent(const Key &key)
Record a begin event with key if Category is enabled.
Definition: collector.h:133
Default Trace category which corresponds to events stored for TRACE_ macros.
Definition: collector.h:100
void EndEventAtTime(const Key &key, double ms)
Record an end event with key at a specified time if Category is enabled.
Definition: collector.h:175
void ScopeArgs(Args &&...args)
Record multiple data events with category cat if Category is enabled.
Definition: collector.h:287
void BeginScope(const TraceKey &key, Args &&...args)
Record a begin event for a scope described by key and a specified category and store data arguments i...
Definition: collector.h:227
TimeStamp MarkerEvent(const Key &key)
Record a marker event with key if Category is enabled.
Definition: collector.h:188
static TRACE_API TraceCollector & GetInstance()
Returns the singleton instance.
Definition: collector.h:84
This is a singleton class that records TraceEvent instances and populates TraceCollection instances...
Definition: collector.h:71
void EndScope(const TraceKey &key)
Record an end event described by key if Category is enabled.
Definition: collector.h:260
void Scope(const TraceKey &key, TimeStamp start)
Record a scope event described by key that started at start if Category is enabled.
Definition: collector.h:274
void RecordCounterDelta(const Key &key, double delta)
Record a counter delta for a name key if Category is enabled.
Definition: collector.h:354
Structure passed to python trace functions.
Definition: pyTracing.h:41
static T & GetInstance()
Return a reference to an object of type T, creating it if necessary.
Definition: singleton.h:137
void BeginScope(const TraceKey &_key)
Record a begin event for a scope described by key if Category is enabled.
Definition: collector.h:214
This class represents an ordered collection of TraceEvents and the TraceDynamicKeys and data that the...
Definition: eventList.h:46
void ScopeArgs(Args &&...args)
Record multiple data events with the default category if collection of events is enabled.
Definition: collector.h:305
static bool IsEnabled()
Returns whether collection of events is enabled for DefaultCategory.
Definition: collector.h:94
uint32_t TraceCategoryId
Categories that a TraceReporter can use to filter events.
Definition: category.h:44
Enable a concrete base class for use with TfWeakPtr.
Definition: weakBase.h:142
void RecordCounterDelta(const TraceKey &key, double delta)
Record a counter delta for a name key if Category is enabled.
Definition: collector.h:342
A wrapper around a TraceStaticKeyData pointer that is stored in TraceEvent instances.
Definition: key.h:40