Tracer.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <AnKi/Util/Thread.h>
  7. #include <AnKi/Util/WeakArray.h>
  8. #include <AnKi/Util/DynamicArray.h>
  9. #include <AnKi/Util/Singleton.h>
  10. #include <AnKi/Util/String.h>
  11. namespace anki {
  12. /// @addtogroup util_other
  13. /// @{
  14. /// @memberof Tracer
  15. class TracerEventHandle
  16. {
  17. friend class Tracer;
  18. private:
  19. Second m_start;
  20. };
  21. /// @memberof Tracer
  22. class TracerEvent
  23. {
  24. public:
  25. CString m_name;
  26. Second m_start;
  27. Second m_duration;
  28. TracerEvent()
  29. {
  30. // No init
  31. }
  32. };
  33. /// @memberof Tracer
  34. class TracerCounter
  35. {
  36. public:
  37. CString m_name;
  38. U64 m_value;
  39. TracerCounter()
  40. {
  41. // No init
  42. }
  43. };
  44. /// Tracer flush callback.
  45. /// @memberof Tracer
  46. using TracerFlushCallback = void (*)(void* userData, ThreadId tid, ConstWeakArray<TracerEvent> events,
  47. ConstWeakArray<TracerCounter> counters);
  48. /// Tracer.
  49. class Tracer
  50. {
  51. public:
  52. Tracer(GenericMemoryPoolAllocator<U8> alloc)
  53. : m_alloc(alloc)
  54. {
  55. }
  56. Tracer(const Tracer&) = delete; // Non-copyable
  57. ~Tracer();
  58. Tracer& operator=(const Tracer&) = delete; // Non-copyable
  59. /// Begin a new event.
  60. /// @note It's thread-safe.
  61. ANKI_USE_RESULT TracerEventHandle beginEvent();
  62. /// End the event that got started with beginEvent().
  63. /// @note It's thread-safe.
  64. void endEvent(const char* eventName, TracerEventHandle event);
  65. /// Add a custom event.
  66. /// @note It's thread-safe.
  67. void addCustomEvent(const char* eventName, Second start, Second duration);
  68. /// Increment a counter.
  69. /// @note It's thread-safe.
  70. void incrementCounter(const char* counterName, U64 value);
  71. /// Flush all counters and events and start clean. The callback will be called multiple times.
  72. /// @note It's thread-safe.
  73. void flush(TracerFlushCallback callback, void* callbackUserData);
  74. Bool getEnabled() const
  75. {
  76. return m_enabled;
  77. }
  78. void setEnabled(Bool enabled)
  79. {
  80. m_enabled = enabled;
  81. }
  82. private:
  83. static constexpr U32 EVENTS_PER_CHUNK = 256;
  84. static constexpr U32 COUNTERS_PER_CHUNK = 512;
  85. class ThreadLocal;
  86. class Chunk;
  87. GenericMemoryPoolAllocator<U8> m_alloc;
  88. static thread_local ThreadLocal* m_threadLocal;
  89. DynamicArray<ThreadLocal*> m_allThreadLocal; ///< The Tracer should know about all the ThreadLocal.
  90. Mutex m_allThreadLocalMtx;
  91. Bool m_enabled = false;
  92. /// Get the thread local ThreadLocal structure.
  93. /// @note Thread-safe.
  94. ThreadLocal& getThreadLocal();
  95. /// Get or create a new chunk.
  96. Chunk& getOrCreateChunk(ThreadLocal& tlocal);
  97. };
  98. /// The global tracer.
  99. using TracerSingleton = SingletonInit<Tracer>;
  100. /// Scoped tracer event.
  101. class TracerScopedEvent
  102. {
  103. public:
  104. TracerScopedEvent(const char* name)
  105. : m_name(name)
  106. , m_tracer(&TracerSingleton::get())
  107. {
  108. m_handle = m_tracer->beginEvent();
  109. }
  110. ~TracerScopedEvent()
  111. {
  112. m_tracer->endEvent(m_name, m_handle);
  113. }
  114. private:
  115. const char* m_name;
  116. TracerEventHandle m_handle;
  117. Tracer* m_tracer;
  118. };
  119. #if ANKI_ENABLE_TRACE
  120. # define ANKI_TRACE_SCOPED_EVENT(name_) TracerScopedEvent _tse##name_(# name_)
  121. # define ANKI_TRACE_CUSTOM_EVENT(name_, start_, duration_) \
  122. TracerSingleton::get().addCustomEvent(#name_, start_, duration_)
  123. # define ANKI_TRACE_INC_COUNTER(name_, val_) TracerSingleton::get().incrementCounter(# name_, val_)
  124. #else
  125. # define ANKI_TRACE_SCOPED_EVENT(name_) ((void)0)
  126. # define ANKI_TRACE_CUSTOM_EVENT(name_, start_, duration_) ((void)0)
  127. # define ANKI_TRACE_INC_COUNTER(name_, val_) ((void)0)
  128. #endif
  129. /// @}
  130. } // end namespace anki