UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
CountersTrace.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreTypes.h"
7#include "Misc/Build.h"
9#include "Trace/Config.h"
12#include "Trace/Trace.h"
13
14#include <atomic>
15
16#if !defined(COUNTERSTRACE_ENABLED)
17#if UE_TRACE_ENABLED && !UE_BUILD_SHIPPING
18#define COUNTERSTRACE_ENABLED 1
19#else
20#define COUNTERSTRACE_ENABLED 0
21#endif
22#endif
23
29
35
37{
38 TraceCounterNameType_Static = 0, // TCounter is allowed to keep a pointer to InCounterName string
39 TraceCounterNameType_Dynamic = 0x10, // TCounter needs to copy the InCounterName string
40 TraceCounterNameType_AllocNameCopy = 0x20, // TCounter has allocated a copy of the InCounterName string
41};
42
43#if COUNTERSTRACE_ENABLED
44
46
47struct FCountersTrace
48{
51 CORE_API static void OutputSetValue(uint16 CounterId, double Value);
52
54 CORE_API static void FreeCounterName(const TCHAR* InCounterName);
55
56 template<typename ValueType, ETraceCounterType CounterType, typename StoredType = ValueType, bool bUnchecked = false>
57 class TCounter
58 {
59 public:
60 TCounter() = delete;
61
62 template<int N>
64 : Value(0)
65 , CounterName(InCounterName) // assumes that InCounterName is a static string
66 , CounterId(0)
68 {
70 }
71
73 : Value(0)
75 , CounterId(0)
77 {
79
81 {
82 // Store counter name for late init. Needs a copy as InCounterName pointer might not be valid later.
85 }
86 }
87
88 ~TCounter()
89 {
91 {
93 }
94 }
95
96 void LateInit()
97 {
98 uint32 OldId = CounterId.load();
99 if (!OldId)
100 {
102 CounterId.compare_exchange_weak(OldId, NewId);
103 }
104 }
105
106 ValueType Get() const
107 {
108 return Value;
109 }
110
111 void Set(ValueType InValue)
112 {
113 if (bUnchecked || Value != InValue)
114 {
115 Value = InValue;
117 {
118 LateInit();
120 }
121 }
122 }
123
124 void SetIfDifferent(ValueType InValue)
125 {
126 if (Value != InValue)
127 {
128 Value = InValue;
130 {
131 LateInit();
133 }
134 }
135 }
136
137 void SetAlways(ValueType InValue)
138 {
139 Value = InValue;
141 {
142 LateInit();
144 }
145 }
146
147 void Add(ValueType InValue)
148 {
149 if (bUnchecked || InValue != 0)
150 {
151 Value += InValue;
153 {
154 LateInit();
156 }
157 }
158 }
159
160 void AddIfNotZero(ValueType InValue)
161 {
162 if (InValue != 0)
163 {
164 Value += InValue;
166 {
167 LateInit();
169 }
170 }
171 }
172
173 void AddAlways(ValueType InValue)
174 {
175 Value += InValue;
177 {
178 LateInit();
180 }
181 }
182
183 void Subtract(ValueType InValue)
184 {
185 if (bUnchecked || InValue != 0)
186 {
187 Value -= InValue;
189 {
190 LateInit();
192 }
193 }
194 }
195
196 void SubtractIfNotZero(ValueType InValue)
197 {
198 if (InValue != 0)
199 {
200 Value -= InValue;
202 {
203 LateInit();
205 }
206 }
207 }
208
209 void SubtractAlways(ValueType InValue)
210 {
211 Value -= InValue;
213 {
214 LateInit();
216 }
217 }
218
219 void Increment()
220 {
221 ++Value;
223 {
224 LateInit();
226 }
227 }
228
229 void Decrement()
230 {
231 --Value;
233 {
234 LateInit();
236 }
237 }
238
239 private:
241 const TCHAR* CounterName;
242 std::atomic<uint32> CounterId;
243 uint8 CounterFlags; // stores a combination of ETraceCounterDisplayHint and ETraceCounterNameType flags
244 };
245
250
255};
256
258// Inline Counters
259
260#define __TRACE_CHECK_COUNTER_NAME(CounterDisplayName) \
261 static_assert(std::is_const_v<std::remove_reference_t<decltype(CounterDisplayName)>>, "CounterDisplayName string must be a const TCHAR array."); \
262 static_assert(TIsArrayOrRefOfTypeByPredicate<decltype(CounterDisplayName), TIsCharEncodingCompatibleWithTCHAR>::Value, "CounterDisplayName string must be a TCHAR array.");
263
264#define __TRACE_DECLARE_INLINE_COUNTER(CounterDisplayName, CounterType, CounterDisplayHint) \
265 __TRACE_CHECK_COUNTER_NAME(CounterDisplayName) \
266 static FCountersTrace::CounterType PREPROCESSOR_JOIN(__TraceCounter, __LINE__)(CounterDisplayName, CounterDisplayHint);
267
268#define __TRACE_INLINE_COUNTER_SET(CounterDisplayName, Value, CounterType, CounterDisplayHint) \
269 __TRACE_DECLARE_INLINE_COUNTER(CounterDisplayName, CounterType, CounterDisplayHint) \
270 PREPROCESSOR_JOIN(__TraceCounter, __LINE__).Set(Value);
271
272#define TRACE_INT_VALUE(CounterDisplayName, Value) __TRACE_INLINE_COUNTER_SET(CounterDisplayName, Value, FCounterInt, TraceCounterDisplayHint_None)
273#define TRACE_ATOMIC_INT_VALUE(CounterDisplayName, Value) __TRACE_INLINE_COUNTER_SET(CounterDisplayName, Value, FCounterAtomicInt, TraceCounterDisplayHint_None)
274#define TRACE_FLOAT_VALUE(CounterDisplayName, Value) __TRACE_INLINE_COUNTER_SET(CounterDisplayName, Value, FCounterFloat, TraceCounterDisplayHint_None)
275#define TRACE_ATOMIC_FLOAT_VALUE(CounterDisplayName, Value) __TRACE_INLINE_COUNTER_SET(CounterDisplayName, Value, FCounterAtomicFloat, TraceCounterDisplayHint_None)
276#define TRACE_MEMORY_VALUE(CounterDisplayName, Value) __TRACE_INLINE_COUNTER_SET(CounterDisplayName, Value, FCounterInt, TraceCounterDisplayHint_Memory)
277#define TRACE_ATOMIC_MEMORY_VALUE(CounterDisplayName, Value) __TRACE_INLINE_COUNTER_SET(CounterDisplayName, Value, FCounterAtomicInt, TraceCounterDisplayHint_Memory)
278
279#define TRACE_UNCHECKED_INT_VALUE(CounterDisplayName, Value) __TRACE_INLINE_COUNTER_SET(CounterDisplayName, Value, FCounterUncheckedInt, TraceCounterDisplayHint_None)
280#define TRACE_UNCHECKED_ATOMIC_INT_VALUE(CounterDisplayName, Value) __TRACE_INLINE_COUNTER_SET(CounterDisplayName, Value, FCounterUncheckedAtomicInt, TraceCounterDisplayHint_None)
281#define TRACE_UNCHECKED_FLOAT_VALUE(CounterDisplayName, Value) __TRACE_INLINE_COUNTER_SET(CounterDisplayName, Value, FCounterUncheckedFloat, TraceCounterDisplayHint_None)
282#define TRACE_UNCHECKED_ATOMIC_FLOAT_VALUE(CounterDisplayName, Value) __TRACE_INLINE_COUNTER_SET(CounterDisplayName, Value, FCounterUncheckedAtomicFloat, TraceCounterDisplayHint_None)
283#define TRACE_UNCHECKED_MEMORY_VALUE(CounterDisplayName, Value) __TRACE_INLINE_COUNTER_SET(CounterDisplayName, Value, FCounterUncheckedInt, TraceCounterDisplayHint_Memory)
284#define TRACE_UNCHECKED_ATOMIC_MEMORY_VALUE(CounterDisplayName, Value) __TRACE_INLINE_COUNTER_SET(CounterDisplayName, Value, FCounterUncheckedAtomicInt, TraceCounterDisplayHint_Memory)
285
287
288#define TRACE_DECLARE_COUNTER(CounterType, CounterName, CounterDisplayName, CounterDisplayHint) \
289 __TRACE_CHECK_COUNTER_NAME(CounterDisplayName) \
290 FCountersTrace::CounterType PREPROCESSOR_JOIN(__GTraceCounter, CounterName)(CounterDisplayName, CounterDisplayHint);
291
293// Declare Int Counters
294
295#define TRACE_DECLARE_INT_COUNTER(CounterName, CounterDisplayName) \
296 TRACE_DECLARE_COUNTER(FCounterInt, CounterName, CounterDisplayName, TraceCounterDisplayHint_None)
297
298#define TRACE_DECLARE_UNCHECKED_INT_COUNTER(CounterName, CounterDisplayName) \
299 TRACE_DECLARE_COUNTER(FCounterUncheckedInt, CounterName, CounterDisplayName, TraceCounterDisplayHint_None)
300
301#define TRACE_DECLARE_INT_COUNTER_EXTERN(CounterName) \
302 extern FCountersTrace::FCounterInt PREPROCESSOR_JOIN(__GTraceCounter, CounterName);
303
304#define TRACE_DECLARE_UNCHECKED_INT_COUNTER_EXTERN(CounterName) \
305 extern FCountersTrace::FCounterUncheckedInt PREPROCESSOR_JOIN(__GTraceCounter, CounterName);
306
308// Declare Atomic Int Counters
309
310#define TRACE_DECLARE_ATOMIC_INT_COUNTER(CounterName, CounterDisplayName) \
311 TRACE_DECLARE_COUNTER(FCounterAtomicInt, CounterName, CounterDisplayName, TraceCounterDisplayHint_None)
312
313#define TRACE_DECLARE_UNCHECKED_ATOMIC_INT_COUNTER(CounterName, CounterDisplayName) \
314 TRACE_DECLARE_COUNTER(FCounterUncheckedAtomicInt, CounterName, CounterDisplayName, TraceCounterDisplayHint_None)
315
316#define TRACE_DECLARE_ATOMIC_INT_COUNTER_EXTERN(CounterName) \
317 extern FCountersTrace::FCounterAtomicInt PREPROCESSOR_JOIN(__GTraceCounter, CounterName);
318
319#define TRACE_DECLARE_UNCHECKED_ATOMIC_INT_COUNTER_EXTERN(CounterName) \
320 extern FCountersTrace::FCounterUncheckedAtomicInt PREPROCESSOR_JOIN(__GTraceCounter, CounterName);
321
323// Declare Float Counters
324
325#define TRACE_DECLARE_FLOAT_COUNTER(CounterName, CounterDisplayName) \
326 TRACE_DECLARE_COUNTER(FCounterFloat, CounterName, CounterDisplayName, TraceCounterDisplayHint_None)
327
328#define TRACE_DECLARE_UNCHECKED_FLOAT_COUNTER(CounterName, CounterDisplayName) \
329 TRACE_DECLARE_COUNTER(FCounterUncheckedFloat, CounterName, CounterDisplayName, TraceCounterDisplayHint_None)
330
331#define TRACE_DECLARE_FLOAT_COUNTER_EXTERN(CounterName) \
332 extern FCountersTrace::FCounterFloat PREPROCESSOR_JOIN(__GTraceCounter, CounterName);
333
334#define TRACE_DECLARE_UNCHECKED_FLOAT_COUNTER_EXTERN(CounterName) \
335 extern FCountersTrace::FCounterUncheckedFloat PREPROCESSOR_JOIN(__GTraceCounter, CounterName);
336
338// Declare Atomic Float Counters
339
340#define TRACE_DECLARE_ATOMIC_FLOAT_COUNTER(CounterName, CounterDisplayName) \
341 TRACE_DECLARE_COUNTER(FCounterAtomicFloat, CounterName, CounterDisplayName, TraceCounterDisplayHint_None)
342
343#define TRACE_DECLARE_UNCHECKED_ATOMIC_FLOAT_COUNTER(CounterName, CounterDisplayName) \
344 TRACE_DECLARE_COUNTER(FCounterUncheckedAtomicFloat, CounterName, CounterDisplayName, TraceCounterDisplayHint_None)
345
346#define TRACE_DECLARE_ATOMIC_FLOAT_COUNTER_EXTERN(CounterName) \
347 extern FCountersTrace::FCounterAtomicFloat PREPROCESSOR_JOIN(__GTraceCounter, CounterName);
348
349#define TRACE_DECLARE_UNCHECKED_ATOMIC_FLOAT_COUNTER_EXTERN(CounterName) \
350 extern FCountersTrace::FCounterUncheckedAtomicFloat PREPROCESSOR_JOIN(__GTraceCounter, CounterName);
351
353// Declare Memory Counters
354
355#define TRACE_DECLARE_MEMORY_COUNTER(CounterName, CounterDisplayName) \
356 TRACE_DECLARE_COUNTER(FCounterInt, CounterName, CounterDisplayName, TraceCounterDisplayHint_Memory)
357
358#define TRACE_DECLARE_UNCHECKED_MEMORY_COUNTER(CounterName, CounterDisplayName) \
359 TRACE_DECLARE_COUNTER(FCounterUncheckedInt, CounterName, CounterDisplayName, TraceCounterDisplayHint_Memory)
360
361#define TRACE_DECLARE_MEMORY_COUNTER_EXTERN(CounterName) \
362 TRACE_DECLARE_INT_COUNTER_EXTERN(CounterName)
363
364#define TRACE_DECLARE_UNCHECKED_MEMORY_COUNTER_EXTERN(CounterName) \
365 TRACE_DECLARE_UNCHECKED_INT_COUNTER_EXTERN(CounterName)
366
368// Declare Atomic Memory Counters
369
370#define TRACE_DECLARE_ATOMIC_MEMORY_COUNTER(CounterName, CounterDisplayName) \
371 TRACE_DECLARE_COUNTER(FCounterAtomicInt, CounterName, CounterDisplayName, TraceCounterDisplayHint_Memory)
372
373#define TRACE_DECLARE_UNCHECKED_ATOMIC_MEMORY_COUNTER(CounterName, CounterDisplayName) \
374 TRACE_DECLARE_COUNTER(FCounterUncheckedAtomicInt, CounterName, CounterDisplayName, TraceCounterDisplayHint_Memory)
375
376#define TRACE_DECLARE_ATOMIC_MEMORY_COUNTER_EXTERN(CounterName) \
377 TRACE_DECLARE_ATOMIC_INT_COUNTER_EXTERN(CounterName)
378
379#define TRACE_DECLARE_UNCHECKED_ATOMIC_MEMORY_COUNTER_EXTERN(CounterName) \
380 TRACE_DECLARE_UNCHECKED_ATOMIC_INT_COUNTER_EXTERN(CounterName)
381
383// Counter Operations
384
385// A value that does not change will be traced (or not) depending on how the counter is created.
386
387#define TRACE_COUNTER_SET(CounterName, Value) \
388 PREPROCESSOR_JOIN(__GTraceCounter, CounterName).Set(Value);
389
390#define TRACE_COUNTER_GET(CounterName) \
391 PREPROCESSOR_JOIN(__GTraceCounter, CounterName).Get();
392
393#define TRACE_COUNTER_ADD(CounterName, Value) \
394 PREPROCESSOR_JOIN(__GTraceCounter, CounterName).Add(Value);
395
396#define TRACE_COUNTER_SUBTRACT(CounterName, Value) \
397 PREPROCESSOR_JOIN(__GTraceCounter, CounterName).Subtract(Value);
398
399#define TRACE_COUNTER_INCREMENT(CounterName) \
400 PREPROCESSOR_JOIN(__GTraceCounter, CounterName).Increment();
401
402#define TRACE_COUNTER_DECREMENT(CounterName) \
403 PREPROCESSOR_JOIN(__GTraceCounter, CounterName).Decrement();
404
405// _IF_DIFFERENT / _IF_NOT_ZERO
406// It will not trace a value that doesn't change (no matter how the counter was created).
407
408#define TRACE_COUNTER_SET_IF_DIFFERENT(CounterName, Value) \
409 PREPROCESSOR_JOIN(__GTraceCounter, CounterName).SetIfDifferent(Value);
410
411#define TRACE_COUNTER_ADD_IF_NOT_ZERO(CounterName, Value) \
412 PREPROCESSOR_JOIN(__GTraceCounter, CounterName).AddIfNotZero(Value);
413
414#define TRACE_COUNTER_SUBTRACT_IF_NOT_ZERO(CounterName, Value) \
415 PREPROCESSOR_JOIN(__GTraceCounter, CounterName).SubtractIfNotZero(Value);
416
417// _ALWAYS
418// It will trace even if value doesn't change (no matter how the counter was created).
419
420#define TRACE_COUNTER_SET_ALWAYS(CounterName, Value) \
421 PREPROCESSOR_JOIN(__GTraceCounter, CounterName).SetAlways(Value);
422
423#define TRACE_COUNTER_ADD_ALWAYS(CounterName, Value) \
424 PREPROCESSOR_JOIN(__GTraceCounter, CounterName).AddAlways(Value);
425
426#define TRACE_COUNTER_SUBTRACT_ALWAYS(CounterName, Value) \
427 PREPROCESSOR_JOIN(__GTraceCounter, CounterName).SubtractAlways(Value);
428
429#else // COUNTERSTRACE_ENABLED
430
431#define TRACE_INT_VALUE(CounterDisplayName, Value)
432#define TRACE_ATOMIC_INT_VALUE(CounterDisplayName, Value)
433#define TRACE_FLOAT_VALUE(CounterDisplayName, Value)
434#define TRACE_ATOMIC_FLOAT_VALUE(CounterDisplayName, Value)
435#define TRACE_MEMORY_VALUE(CounterDisplayName, Value)
436#define TRACE_ATOMIC_MEMORY_VALUE(CounterDisplayName, Value)
437
438#define TRACE_UNCHECKED_INT_VALUE(CounterDisplayName, Value)
439#define TRACE_UNCHECKED_ATOMIC_INT_VALUE(CounterDisplayName, Value)
440#define TRACE_UNCHECKED_FLOAT_VALUE(CounterDisplayName, Value)
441#define TRACE_UNCHECKED_ATOMIC_FLOAT_VALUE(CounterDisplayName, Value)
442#define TRACE_UNCHECKED_MEMORY_VALUE(CounterDisplayName, Value)
443#define TRACE_UNCHECKED_ATOMIC_MEMORY_VALUE(CounterDisplayName, Value)
444
445#define TRACE_DECLARE_COUNTER(CounterType, CounterName, CounterDisplayName, CounterDisplayHint)
446
447#define TRACE_DECLARE_INT_COUNTER(CounterName, CounterDisplayName)
448#define TRACE_DECLARE_INT_COUNTER_EXTERN(CounterName)
449#define TRACE_DECLARE_ATOMIC_INT_COUNTER(CounterName, CounterDisplayName)
450#define TRACE_DECLARE_ATOMIC_INT_COUNTER_EXTERN(CounterName)
451#define TRACE_DECLARE_FLOAT_COUNTER(CounterName, CounterDisplayName)
452#define TRACE_DECLARE_FLOAT_COUNTER_EXTERN(CounterName)
453#define TRACE_DECLARE_ATOMIC_FLOAT_COUNTER(CounterName, CounterDisplayName)
454#define TRACE_DECLARE_ATOMIC_FLOAT_COUNTER_EXTERN(CounterName)
455#define TRACE_DECLARE_MEMORY_COUNTER(CounterName, CounterDisplayName)
456#define TRACE_DECLARE_MEMORY_COUNTER_EXTERN(CounterName)
457#define TRACE_DECLARE_ATOMIC_MEMORY_COUNTER(CounterName, CounterDisplayName)
458#define TRACE_DECLARE_ATOMIC_MEMORY_COUNTER_EXTERN(CounterName)
459
460#define TRACE_DECLARE_UNCHECKED_INT_COUNTER(CounterName, CounterDisplayName)
461#define TRACE_DECLARE_UNCHECKED_INT_COUNTER_EXTERN(CounterName)
462#define TRACE_DECLARE_UNCHECKED_ATOMIC_INT_COUNTER(CounterName, CounterDisplayName)
463#define TRACE_DECLARE_UNCHECKED_ATOMIC_INT_COUNTER_EXTERN(CounterName)
464#define TRACE_DECLARE_UNCHECKED_FLOAT_COUNTER(CounterName, CounterDisplayName)
465#define TRACE_DECLARE_UNCHECKED_FLOAT_COUNTER_EXTERN(CounterName)
466#define TRACE_DECLARE_UNCHECKED_ATOMIC_FLOAT_COUNTER(CounterName, CounterDisplayName)
467#define TRACE_DECLARE_UNCHECKED_ATOMIC_FLOAT_COUNTER_EXTERN(CounterName)
468#define TRACE_DECLARE_UNCHECKED_MEMORY_COUNTER(CounterName, CounterDisplayName)
469#define TRACE_DECLARE_UNCHECKED_MEMORY_COUNTER_EXTERN(CounterName)
470#define TRACE_DECLARE_UNCHECKED_ATOMIC_MEMORY_COUNTER(CounterName, CounterDisplayName)
471#define TRACE_DECLARE_UNCHECKED_ATOMIC_MEMORY_COUNTER_EXTERN(CounterName)
472
473#define TRACE_COUNTER_SET(CounterName, Value)
474#define TRACE_COUNTER_GET(CounterName) {}
475#define TRACE_COUNTER_ADD(CounterName, Value)
476#define TRACE_COUNTER_SUBTRACT(CounterName, Value)
477#define TRACE_COUNTER_INCREMENT(CounterName)
478#define TRACE_COUNTER_DECREMENT(CounterName)
479
480#define TRACE_COUNTER_SET_IF_DIFFERENT(CounterName, Value)
481#define TRACE_COUNTER_ADD_IF_NOT_ZERO(CounterName, Value)
482#define TRACE_COUNTER_SUBTRACT_IF_NOT_ZERO(CounterName, Value)
483
484#define TRACE_COUNTER_SET_ALWAYS(CounterName, Value)
485#define TRACE_COUNTER_ADD_ALWAYS(CounterName, Value)
486#define TRACE_COUNTER_SUBTRACT_ALWAYS(CounterName, Value)
487
488#endif // COUNTERSTRACE_ENABLED
FPlatformTypes::TCHAR TCHAR
Either ANSICHAR or WIDECHAR, depending on whether the platform supports wide characters or the requir...
Definition Platform.h:1135
FPlatformTypes::int64 int64
A 64-bit signed integer.
Definition Platform.h:1127
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
ETraceCounterType
Definition CountersTrace.h:25
@ TraceCounterType_Float
Definition CountersTrace.h:27
@ TraceCounterType_Int
Definition CountersTrace.h:26
ETraceCounterDisplayHint
Definition CountersTrace.h:31
@ TraceCounterDisplayHint_Memory
Definition CountersTrace.h:33
@ TraceCounterDisplayHint_None
Definition CountersTrace.h:32
ETraceCounterNameType
Definition CountersTrace.h:37
@ TraceCounterNameType_Dynamic
Definition CountersTrace.h:39
@ TraceCounterNameType_Static
Definition CountersTrace.h:38
@ TraceCounterNameType_AllocNameCopy
Definition CountersTrace.h:40
#define UE_TRACE_CHANNELEXPR_IS_ENABLED(ChannelsExpr)
Definition Trace.h:452
#define UE_TRACE_CHANNEL_EXTERN(ChannelName,...)
Definition Trace.h:448
uint8_t uint8
Definition binka_ue_file_header.h:8
uint16_t uint16
Definition binka_ue_file_header.h:7
uint32_t uint32
Definition binka_ue_file_header.h:6
FORCEINLINE T * Get(const FObjectPtr &ObjectPtr)
Definition ObjectPtr.h:426