24 template <typename EventVariant>
27 template <
typename EventVariant>
36 [[nodiscard]]
static constexpr uint64_t
nowNs() noexcept {
return 0; }
55template <std::
size_t Capacity = 1024>
86template <std::
size_t QueueCapacity = 1024>
91 [[nodiscard]] static uint64_t
nowNs() noexcept
93 return static_cast<uint64_t
>(
94 std::chrono::duration_cast<std::chrono::nanoseconds>(
95 ProfilerClock::now().time_since_epoch()
104 if (!_enabled.load(std::memory_order_relaxed))
return;
114 template <
typename EventVariant>
117 if (!_enabled.load(std::memory_order_relaxed))
return;
118 _totalPosted.fetch_add(1, std::memory_order_relaxed);
121 template <
typename EventVariant>
126 uint64_t dispatchTimeNs,
127 uint64_t finishTimeNs
130 if (!_enabled.load(std::memory_order_relaxed))
return;
132 const uint64_t queueLatencyNs = (dispatchTimeNs > postTimeNs) ? (dispatchTimeNs - postTimeNs) : 0;
133 const uint64_t execDurationNs = (finishTimeNs > dispatchTimeNs) ? (finishTimeNs - dispatchTimeNs) : 0;
135 _totalDispatched.fetch_add(1, std::memory_order_relaxed);
136 _totalQueueLatencyNs.fetch_add(queueLatencyNs, std::memory_order_relaxed);
137 _totalExecDurationNs.fetch_add(execDurationNs, std::memory_order_relaxed);
140 uint64_t currentMaxLat = _maxQueueLatencyNs.load(std::memory_order_relaxed);
141 while (queueLatencyNs > currentMaxLat &&
142 !_maxQueueLatencyNs.compare_exchange_weak(currentMaxLat, queueLatencyNs, std::memory_order_relaxed)) {}
145 uint64_t currentMinLat = _minQueueLatencyNs.load(std::memory_order_relaxed);
146 while (queueLatencyNs < currentMinLat &&
147 !_minQueueLatencyNs.compare_exchange_weak(currentMinLat, queueLatencyNs, std::memory_order_relaxed)) {}
150 uint64_t currentMaxExec = _maxExecDurationNs.load(std::memory_order_relaxed);
151 while (execDurationNs > currentMaxExec &&
152 !_maxExecDurationNs.compare_exchange_weak(currentMaxExec, execDurationNs, std::memory_order_relaxed)) {}
158 _enabled.store(enabled, std::memory_order_release);
170 return _enabled.load(std::memory_order_acquire);
176 return _totalPosted.load(std::memory_order_relaxed);
182 return _totalDispatched.load(std::memory_order_relaxed);
188 const uint64_t val = _minQueueLatencyNs.load(std::memory_order_relaxed);
189 return val == UINT64_MAX ? 0.0 :
static_cast<double>(val) / 1000.0;
195 return static_cast<double>(_maxQueueLatencyNs.load(std::memory_order_relaxed)) / 1000.0;
201 const uint64_t count = _totalDispatched.load(std::memory_order_relaxed);
202 if (count == 0)
return 0.0;
203 return static_cast<double>(_totalQueueLatencyNs.load(std::memory_order_relaxed)) / (
static_cast<double>(count) * 1000.0);
209 return static_cast<double>(_maxExecDurationNs.load(std::memory_order_relaxed)) / 1000.0;
215 const uint64_t count = _totalDispatched.load(std::memory_order_relaxed);
216 if (count == 0)
return 0.0;
217 return static_cast<double>(_totalExecDurationNs.load(std::memory_order_relaxed)) / (
static_cast<double>(count) * 1000.0);
223 _totalPosted.store(0, std::memory_order_relaxed);
224 _totalDispatched.store(0, std::memory_order_relaxed);
225 _totalQueueLatencyNs.store(0, std::memory_order_relaxed);
226 _totalExecDurationNs.store(0, std::memory_order_relaxed);
227 _maxQueueLatencyNs.store(0, std::memory_order_relaxed);
228 _minQueueLatencyNs.store(UINT64_MAX, std::memory_order_relaxed);
229 _maxExecDurationNs.store(0, std::memory_order_relaxed);
235 std::atomic<bool> _enabled{
true};
236 std::atomic<uint64_t> _totalPosted{0};
237 std::atomic<uint64_t> _totalDispatched{0};
238 std::atomic<uint64_t> _totalQueueLatencyNs{0};
239 std::atomic<uint64_t> _totalExecDurationNs{0};
240 std::atomic<uint64_t> _maxQueueLatencyNs{0};
241 std::atomic<uint64_t> _minQueueLatencyNs{UINT64_MAX};
242 std::atomic<uint64_t> _maxExecDurationNs{0};
250template <std::
size_t BufferCapacity = 256, std::
size_t QueueCapacity = 1024>
255 template <
typename EventVariant>
257 const EventVariant& event,
260 uint64_t dispatchTimeNs,
261 uint64_t finishTimeNs
268 const std::size_t typeIndex =
event.index();
269 const char* name =
"Event";
271 _flightRecorder.record(typeIndex, name, postTimeNs, dispatchTimeNs, finishTimeNs, priority);
277 return _flightRecorder;
283 _flightRecorder.exportChromeTracingJson(os);
Circular in-memory telemetry buffer with Chrome Tracing JSON export.
Lock-free Multi-Producer Single-Consumer (MPSC) bounded ring buffer based on Dmitry Vyukov's algorith...
Lock-free Multiple-Producer, Single-Consumer (MPSC) RingBuffer. Implements Dmitry Vyukov's algorithm ...
Definition MpscRingBuffer.hpp:33
bool tryPop(T &result)
Pop an item from the queue (Single-Consumer only).
Definition MpscRingBuffer.hpp:115
PushResult tryPush(Args &&... args)
Push an item into the queue (Multi-Producer thread safe).
Definition MpscRingBuffer.hpp:86
Combined Flight Recorder and Latency Tracker Profiler. Records historical event traces into a circula...
Definition ProfilerPolicies.hpp:251
FlightRecorderProfiler()=default
void exportChromeTracingJson(std::ostream &os) const
Export flight recorder traces to Chrome Tracing JSON.
Definition ProfilerPolicies.hpp:281
void onEventDispatched(const EventVariant &event, uint8_t priority, uint64_t postTimeNs, uint64_t dispatchTimeNs, uint64_t finishTimeNs) noexcept
Definition ProfilerPolicies.hpp:256
const FlightRecorder< BufferCapacity > & flightRecorder() const noexcept
Access reference to underlying circular flight recorder.
Definition ProfilerPolicies.hpp:275
Zero-heap circular flight recorder storing the last N event telemetry records. Thread-safe for multip...
Definition FlightRecorder.hpp:57
Real-time event latency and performance statistics tracker. Zero dynamic memory allocation....
Definition ProfilerPolicies.hpp:87
void enable() noexcept
Enable runtime profiling.
Definition ProfilerPolicies.hpp:162
bool isEnabled() const noexcept
Check if runtime profiling is enabled.
Definition ProfilerPolicies.hpp:168
LatencyTracker() noexcept=default
void recordPostTime(uint64_t postNs) noexcept
Record the wall-clock post timestamp for the event being pushed now. Called by EventBus::post() immed...
Definition ProfilerPolicies.hpp:102
double maxExecutionDurationUs() const noexcept
Maximum handler execution duration in microseconds.
Definition ProfilerPolicies.hpp:207
void disable() noexcept
Disable runtime profiling.
Definition ProfilerPolicies.hpp:165
double maxQueueLatencyUs() const noexcept
Maximum queue latency in microseconds.
Definition ProfilerPolicies.hpp:193
void onEventPosted(const EventVariant &, uint8_t) noexcept
Definition ProfilerPolicies.hpp:115
uint64_t takePostTime() noexcept
Pop and return the oldest post timestamp (called at dispatch time by EventBus).
Definition ProfilerPolicies.hpp:109
double averageQueueLatencyUs() const noexcept
Average queue latency in microseconds.
Definition ProfilerPolicies.hpp:199
uint64_t totalPosted() const noexcept
Total count of posted events.
Definition ProfilerPolicies.hpp:174
void setEnabled(bool enabled) noexcept
Enable or disable runtime latency profiling.
Definition ProfilerPolicies.hpp:156
double averageExecutionDurationUs() const noexcept
Average handler execution duration in microseconds.
Definition ProfilerPolicies.hpp:213
static uint64_t nowNs() noexcept
Definition ProfilerPolicies.hpp:91
void onEventDispatched(const EventVariant &, uint8_t, uint64_t postTimeNs, uint64_t dispatchTimeNs, uint64_t finishTimeNs) noexcept
Definition ProfilerPolicies.hpp:122
double minQueueLatencyUs() const noexcept
Minimum queue latency in microseconds.
Definition ProfilerPolicies.hpp:186
uint64_t totalDispatched() const noexcept
Total count of dispatched events.
Definition ProfilerPolicies.hpp:180
void resetStats() noexcept
Reset all accumulated statistics.
Definition ProfilerPolicies.hpp:221
Definition ProfilerPolicies.hpp:56
void recordPostTime(uint64_t postNs) noexcept
Record the post timestamp for an event being pushed into the event queue.
Definition ProfilerPolicies.hpp:59
uint64_t takePostTime() noexcept
Pop and return the oldest recorded post timestamp (called at dispatch time).
Definition ProfilerPolicies.hpp:68
Definition FlightRecorder.hpp:16
Default Profiler Policy: Zero-overhead, completely compiled out by inline empty functions.
Definition ProfilerPolicies.hpp:21
constexpr NullProfiler() noexcept=default
void onEventPosted(const EventVariant &, uint8_t) noexcept
Definition ProfilerPolicies.hpp:25
void onEventDispatched(const EventVariant &, uint8_t, uint64_t, uint64_t, uint64_t) noexcept
Definition ProfilerPolicies.hpp:28
static constexpr uint64_t nowNs() noexcept
Definition ProfilerPolicies.hpp:36
uint64_t takePostTime() noexcept
No-op: always returns 0 (NullProfiler has no timestamps).
Definition ProfilerPolicies.hpp:42
void recordPostTime(uint64_t) noexcept
No-op: NullProfiler does not track post timestamps.
Definition ProfilerPolicies.hpp:39