UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
Stats.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreGlobals.h"
6#include "CoreTypes.h"
7#include "StatsCommon.h"
12
13#if UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_6
14// These includes are no longer required for this file.
15#include "Delegates/Delegate.h"
16#include "HAL/PlatformTime.h"
17#include "HAL/ThreadSingleton.h"
19#include "AutoRTFM.h"
20#include "Math/Color.h"
21#include "UObject/NameTypes.h"
22
23// Include these directly where needed instead.
24#include "Stats/StatsCommand.h"
25#include "Stats/StatsSystem.h"
27#endif // UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_6
28
29// used by the profiler
40
41#if STATS
42 #define STAT(x) x
43#else
44 #define STAT(x)
45#endif
46
47#if STATS
48// ----------------------------------------------------------------------------
49// Stats
50// ----------------------------------------------------------------------------
51// These macros emit events to the stat system as well as to profilers.
52// See official docs for more information on the Stats System.
53// ----------------------------------------------------------------------------
54
55#define DECLARE_STAT_GROUP(Description, StatName, StatCategory, InDefaultEnable, InCompileTimeEnable, InSortByName) \
56struct FStatGroup_##StatName\
57{ \
58 enum \
59 { \
60 DefaultEnable = InDefaultEnable, \
61 CompileTimeEnable = InCompileTimeEnable, \
62 SortByName = InSortByName \
63 }; \
64 static UE_FORCEINLINE_HINT const char* GetGroupName() \
65 { \
66 return #StatName; \
67 } \
68 static UE_FORCEINLINE_HINT const char* GetGroupCategory() \
69 { \
70 return #StatCategory; \
71 } \
72 static UE_FORCEINLINE_HINT const TCHAR* GetDescription() \
73 { \
74 return Description; \
75 } \
76 static UE_FORCEINLINE_HINT bool IsDefaultEnabled() \
77 { \
78 return (bool)DefaultEnable; \
79 } \
80 static UE_FORCEINLINE_HINT bool IsCompileTimeEnable() \
81 { \
82 return (bool)CompileTimeEnable; \
83 } \
84 static UE_FORCEINLINE_HINT bool GetSortByName() \
85 { \
86 return (bool)SortByName; \
87 } \
88};
89
90#define DECLARE_STAT(Description, StatName, GroupName, StatType, StatFlags, MemoryRegion) \
91struct FStat_##StatName\
92{ \
93 typedef FStatGroup_##GroupName TGroup; \
94 static UE_FORCEINLINE_HINT const char* GetStatName() \
95 { \
96 return #StatName; \
97 } \
98 static UE_FORCEINLINE_HINT const TCHAR* GetDescription() \
99 { \
100 return Description; \
101 } \
102 static UE_FORCEINLINE_HINT EStatDataType::Type GetStatType() \
103 { \
104 return StatType; \
105 } \
106 static UE_FORCEINLINE_HINT bool IsClearEveryFrame() \
107 { \
108 return EnumHasAnyFlags(GetFlags(), EStatFlags::ClearEveryFrame); \
109 } \
110 static UE_FORCEINLINE_HINT bool IsCycleStat() \
111 { \
112 return EnumHasAnyFlags(GetFlags(), EStatFlags::CycleStat); \
113 } \
114 static UE_FORCEINLINE_HINT EStatFlags GetFlags() \
115 { \
116 return StatFlags; \
117 } \
118 static UE_FORCEINLINE_HINT FPlatformMemory::EMemoryCounterRegion GetMemoryRegion() \
119 { \
120 return MemoryRegion; \
121 } \
122};
123
124#define GET_STATID(Stat) (StatPtr_##Stat.GetStatId())
125#define GET_STATFNAME(Stat) (StatPtr_##Stat.GetStatFName())
126#define GET_STATDESCRIPTION(Stat) (FStat_##Stat::GetDescription())
127#define GET_STATISEVERYFRAME(Stat) (FStat_##Stat::IsClearEveryFrame())
128#define GET_STATFLAGS(Stat) (FStat_##Stat::GetFlags())
129
130#define STAT_GROUP_TO_FStatGroup(Group) FStatGroup_##Group
131
132/*-----------------------------------------------------------------------------
133 Local
134-----------------------------------------------------------------------------*/
135
136#define DEFINE_STAT(Stat) \
137 struct FThreadSafeStaticStat<FStat_##Stat> StatPtr_##Stat;
138
139#define RETURN_QUICK_DECLARE_CYCLE_STAT(StatId,GroupId) \
140 DECLARE_STAT(TEXT(#StatId),StatId,GroupId,EStatDataType::ST_int64, EStatFlags::ClearEveryFrame | EStatFlags::CycleStat, FPlatformMemory::MCR_Invalid); \
141 static DEFINE_STAT(StatId) \
142 return GET_STATID(StatId);
143
144#define QUICK_USE_CYCLE_STAT(StatId,GroupId) [](){ RETURN_QUICK_DECLARE_CYCLE_STAT(StatId, GroupId); }()
145
146#define DECLARE_CYCLE_STAT(CounterName,StatId,GroupId) \
147 DECLARE_STAT(CounterName,StatId,GroupId,EStatDataType::ST_int64, EStatFlags::ClearEveryFrame | EStatFlags::CycleStat, FPlatformMemory::MCR_Invalid); \
148 static DEFINE_STAT(StatId)
149#define DECLARE_CYCLE_STAT_WITH_FLAGS(CounterName,StatId,GroupId,StatFlags) \
150 DECLARE_STAT(CounterName,StatId,GroupId,EStatDataType::ST_int64, (StatFlags) | EStatFlags::ClearEveryFrame | EStatFlags::CycleStat, FPlatformMemory::MCR_Invalid); \
151 static DEFINE_STAT(StatId)
152#define DECLARE_FLOAT_COUNTER_STAT(CounterName,StatId,GroupId) \
153 DECLARE_STAT(CounterName,StatId,GroupId,EStatDataType::ST_double,EStatFlags::ClearEveryFrame, FPlatformMemory::MCR_Invalid); \
154 static DEFINE_STAT(StatId)
155#define DECLARE_DWORD_COUNTER_STAT(CounterName,StatId,GroupId) \
156 DECLARE_STAT(CounterName,StatId,GroupId,EStatDataType::ST_int64,EStatFlags::ClearEveryFrame, FPlatformMemory::MCR_Invalid); \
157 static DEFINE_STAT(StatId)
158#define DECLARE_FLOAT_ACCUMULATOR_STAT(CounterName,StatId,GroupId) \
159 DECLARE_STAT(CounterName,StatId,GroupId,EStatDataType::ST_double, EStatFlags::None, FPlatformMemory::MCR_Invalid); \
160 static DEFINE_STAT(StatId)
161#define DECLARE_DWORD_ACCUMULATOR_STAT(CounterName,StatId,GroupId) \
162 DECLARE_STAT(CounterName,StatId,GroupId,EStatDataType::ST_int64, EStatFlags::None, FPlatformMemory::MCR_Invalid); \
163 static DEFINE_STAT(StatId)
164
166#define DECLARE_FNAME_STAT(CounterName,StatId,GroupId) \
167 DECLARE_STAT(CounterName,StatId,GroupId,EStatDataType::ST_FName, EStatFlags::None, FPlatformMemory::MCR_Invalid); \
168 static DEFINE_STAT(StatId)
169
171#define DECLARE_PTR_STAT(CounterName,StatId,GroupId)\
172 DECLARE_STAT(CounterName,StatId,GroupId,EStatDataType::ST_Ptr, EStatFlags::None, FPlatformMemory::MCR_Invalid); \
173 static DEFINE_STAT(StatId)
174
175#define DECLARE_MEMORY_STAT(CounterName,StatId,GroupId) \
176 DECLARE_STAT(CounterName,StatId,GroupId,EStatDataType::ST_int64, EStatFlags::None, FPlatformMemory::MCR_Physical); \
177 static DEFINE_STAT(StatId)
178
179#define DECLARE_MEMORY_STAT_POOL(CounterName,StatId,GroupId,Pool) \
180 DECLARE_STAT(CounterName,StatId,GroupId,EStatDataType::ST_int64, EStatFlags::None, Pool); \
181 static DEFINE_STAT(StatId)
182
183/*-----------------------------------------------------------------------------
184 Extern
185-----------------------------------------------------------------------------*/
186
187#define DECLARE_CYCLE_STAT_EXTERN(CounterName,StatId,GroupId, APIX) \
188 DECLARE_STAT(CounterName,StatId,GroupId,EStatDataType::ST_int64, EStatFlags::ClearEveryFrame | EStatFlags::CycleStat, FPlatformMemory::MCR_Invalid); \
189 extern APIX DEFINE_STAT(StatId);
190#define DECLARE_CYCLE_STAT_WITH_FLAGS_EXTERN(CounterName,StatId,GroupId,StatFlags, APIX) \
191 DECLARE_STAT(CounterName,StatId,GroupId,EStatDataType::ST_int64, (StatFlags) | EStatFlags::ClearEveryFrame | EStatFlags::CycleStat, FPlatformMemory::MCR_Invalid); \
192 extern APIX DEFINE_STAT(StatId);
193#define DECLARE_FLOAT_COUNTER_STAT_EXTERN(CounterName,StatId,GroupId, API) \
194 DECLARE_STAT(CounterName,StatId,GroupId,EStatDataType::ST_double, EStatFlags::ClearEveryFrame, FPlatformMemory::MCR_Invalid); \
195 extern API DEFINE_STAT(StatId);
196#define DECLARE_DWORD_COUNTER_STAT_EXTERN(CounterName,StatId,GroupId, API) \
197 DECLARE_STAT(CounterName,StatId,GroupId,EStatDataType::ST_int64, EStatFlags::ClearEveryFrame, FPlatformMemory::MCR_Invalid); \
198 extern API DEFINE_STAT(StatId);
199#define DECLARE_FLOAT_ACCUMULATOR_STAT_EXTERN(CounterName,StatId,GroupId, API) \
200 DECLARE_STAT(CounterName,StatId,GroupId,EStatDataType::ST_double, EStatFlags::None, FPlatformMemory::MCR_Invalid); \
201 extern API DEFINE_STAT(StatId);
202#define DECLARE_DWORD_ACCUMULATOR_STAT_EXTERN(CounterName,StatId,GroupId, API) \
203 DECLARE_STAT(CounterName,StatId,GroupId,EStatDataType::ST_int64, EStatFlags::None, FPlatformMemory::MCR_Invalid); \
204 extern API DEFINE_STAT(StatId);
205
207#define DECLARE_FNAME_STAT_EXTERN(CounterName,StatId,GroupId, API) \
208 DECLARE_STAT(CounterName,StatId,GroupId,EStatDataType::ST_FName, EStatFlags::None, FPlatformMemory::MCR_Invalid); \
209 extern API DEFINE_STAT(StatId);
210
212#define DECLARE_PTR_STAT_EXTERN(CounterName,StatId,GroupId, API) \
213 DECLARE_STAT(CounterName,StatId,GroupId,EStatDataType::ST_Ptr, EStatFlags::None, FPlatformMemory::MCR_Invalid); \
214 extern API DEFINE_STAT(StatId);
215
216#define DECLARE_MEMORY_STAT_EXTERN(CounterName,StatId,GroupId, API) \
217 DECLARE_STAT(CounterName,StatId,GroupId,EStatDataType::ST_int64, EStatFlags::None, FPlatformMemory::MCR_Physical); \
218 extern API DEFINE_STAT(StatId);
219
220#define DECLARE_MEMORY_STAT_POOL_EXTERN(CounterName,StatId,GroupId,Pool, API) \
221 DECLARE_STAT(CounterName,StatId,GroupId,EStatDataType::ST_int64, EStatFlags::None, Pool); \
222 extern API DEFINE_STAT(StatId);
223
225#define DECLARE_STATS_GROUP(GroupDesc, GroupId, GroupCat) \
226 DECLARE_STAT_GROUP(GroupDesc, GroupId, GroupCat, true, true, false);
227
228#define DECLARE_STATS_GROUP_SORTBYNAME(GroupDesc, GroupId, GroupCat) \
229 DECLARE_STAT_GROUP(GroupDesc, GroupId, GroupCat, true, true, true);
230
231#define DECLARE_STATS_GROUP_VERBOSE(GroupDesc, GroupId, GroupCat) \
232 DECLARE_STAT_GROUP(GroupDesc, GroupId, GroupCat, false, true, false);
233
234#define DECLARE_STATS_GROUP_MAYBE_COMPILED_OUT(GroupDesc, GroupId, GroupCat, CompileIn) \
235 DECLARE_STAT_GROUP(GroupDesc, GroupId, GroupCat, false, CompileIn, false);
236
237#define DECLARE_SCOPE_CYCLE_COUNTER(CounterName,Stat,GroupId) \
238 DECLARE_STAT(CounterName,Stat,GroupId,EStatDataType::ST_int64, EStatFlags::ClearEveryFrame | EStatFlags::CycleStat, FPlatformMemory::MCR_Invalid); \
239 static DEFINE_STAT(Stat) \
240 FScopeCycleCounter CycleCount_##Stat(GET_STATID(Stat), GET_STATFLAGS(Stat));
241
242#define QUICK_SCOPE_CYCLE_COUNTER(Stat) \
243 DECLARE_SCOPE_CYCLE_COUNTER(TEXT(#Stat),Stat,STATGROUP_Quick)
244
245#define SCOPE_CYCLE_COUNTER(Stat) \
246 FScopeCycleCounter CycleCount_##Stat(GET_STATID(Stat), GET_STATFLAGS(Stat));
247
248#define SCOPE_CYCLE_COUNTER_STATID(StatId) \
249 FScopeCycleCounter CycleCount_FromStatId(StatId);
250
251#define CONDITIONAL_SCOPE_CYCLE_COUNTER(Stat,bCondition) \
252 FScopeCycleCounter CycleCount_##Stat(bCondition ? GET_STATID(Stat) : TStatId(), GET_STATFLAGS(Stat));
253
254#define SCOPE_SECONDS_ACCUMULATOR(Stat) \
255 FSimpleScopeSecondsStat SecondsAccum_##Stat(GET_STATID(Stat));
256
257#define SCOPE_MS_ACCUMULATOR(Stat) \
258 FSimpleScopeSecondsStat SecondsAccum_##Stat(GET_STATID(Stat), 1000.0);
259
260#define SET_CYCLE_COUNTER(Stat,Cycles) \
261{\
262 if (FThreadStats::IsCollectingData() || !GET_STATISEVERYFRAME(Stat)) \
263 FThreadStats::AddMessage(GET_STATFNAME(Stat), EStatOperation::Set, int64(Cycles), true);\
264}
265
266#define INC_DWORD_STAT(Stat) \
267{\
268 if (FThreadStats::IsCollectingData() || !GET_STATISEVERYFRAME(Stat)) \
269 { \
270 const FName StatName = GET_STATFNAME(Stat); \
271 FThreadStats::AddMessage(StatName, EStatOperation::Add, int64(1));\
272 } \
273}
274#define INC_FLOAT_STAT_BY(Stat, Amount) \
275{\
276 double AddAmount = double(Amount); \
277 if (AddAmount != 0.0) \
278 { \
279 if (FThreadStats::IsCollectingData() || !GET_STATISEVERYFRAME(Stat)) \
280 { \
281 const FName StatName = GET_STATFNAME(Stat); \
282 FThreadStats::AddMessage(StatName, EStatOperation::Add, AddAmount); \
283 } \
284 } \
285}
286#define INC_DWORD_STAT_BY(Stat, Amount) \
287{\
288 int64 AddAmount = int64(Amount); \
289 if (AddAmount != 0) \
290 { \
291 if (FThreadStats::IsCollectingData() || !GET_STATISEVERYFRAME(Stat)) \
292 { \
293 const FName StatName = GET_STATFNAME(Stat); \
294 FThreadStats::AddMessage(StatName, EStatOperation::Add, AddAmount); \
295 } \
296 } \
297}
298#define INC_MEMORY_STAT_BY(Stat, Amount) \
299{\
300 int64 AddAmount = int64(Amount); \
301 if (AddAmount != 0) \
302 { \
303 if (FThreadStats::IsCollectingData() || !GET_STATISEVERYFRAME(Stat)) \
304 { \
305 const FName StatName = GET_STATFNAME(Stat); \
306 FThreadStats::AddMessage(StatName, EStatOperation::Add, AddAmount); \
307 } \
308 } \
309}
310#define DEC_DWORD_STAT(Stat) \
311{\
312 if (FThreadStats::IsCollectingData() || !GET_STATISEVERYFRAME(Stat)) \
313 { \
314 const FName StatName = GET_STATFNAME(Stat); \
315 FThreadStats::AddMessage(StatName, EStatOperation::Subtract, int64(1));\
316 } \
317}
318#define DEC_FLOAT_STAT_BY(Stat,Amount) \
319{\
320 double SubtractAmount = double(Amount); \
321 if (SubtractAmount != 0.0) \
322 { \
323 if (FThreadStats::IsCollectingData() || !GET_STATISEVERYFRAME(Stat)) \
324 { \
325 const FName StatName = GET_STATFNAME(Stat); \
326 FThreadStats::AddMessage(StatName, EStatOperation::Subtract, SubtractAmount); \
327 } \
328 } \
329}
330#define DEC_DWORD_STAT_BY(Stat,Amount) \
331{\
332 int64 SubtractAmount = int64(Amount); \
333 if (SubtractAmount != 0) \
334 { \
335 if (FThreadStats::IsCollectingData() || !GET_STATISEVERYFRAME(Stat)) \
336 { \
337 const FName StatName = GET_STATFNAME(Stat); \
338 FThreadStats::AddMessage(StatName, EStatOperation::Subtract, SubtractAmount); \
339 } \
340 } \
341}
342#define DEC_MEMORY_STAT_BY(Stat,Amount) \
343{\
344 int64 SubtractAmount = int64(Amount); \
345 if (SubtractAmount != 0) \
346 { \
347 if (FThreadStats::IsCollectingData() || !GET_STATISEVERYFRAME(Stat)) \
348 { \
349 const FName StatName = GET_STATFNAME(Stat); \
350 FThreadStats::AddMessage(StatName, EStatOperation::Subtract, SubtractAmount); \
351 } \
352 } \
353}
354#define SET_MEMORY_STAT(Stat,Value) \
355{\
356 if (FThreadStats::IsCollectingData() || !GET_STATISEVERYFRAME(Stat)) \
357 { \
358 const FName StatName = GET_STATFNAME(Stat); \
359 int64 SetValue = int64(Value); \
360 FThreadStats::AddMessage(StatName, EStatOperation::Set, SetValue); \
361 } \
362}
363#define SET_DWORD_STAT(Stat,Value) \
364{\
365 if (FThreadStats::IsCollectingData() || !GET_STATISEVERYFRAME(Stat)) \
366 { \
367 const FName StatName = GET_STATFNAME(Stat); \
368 int64 SetValue = int64(Value); \
369 FThreadStats::AddMessage(StatName, EStatOperation::Set, SetValue); \
370 } \
371}
372#define SET_FLOAT_STAT(Stat,Value) \
373{\
374 if (FThreadStats::IsCollectingData() || !GET_STATISEVERYFRAME(Stat)) \
375 { \
376 const FName StatName = GET_STATFNAME(Stat); \
377 double SetValue = double(Value); \
378 FThreadStats::AddMessage(StatName, EStatOperation::Set, SetValue); \
379 } \
380}
381
382#define STAT_ADD_CUSTOMMESSAGE_NAME(Stat,Value) \
383{\
384 FThreadStats::AddMessage(GET_STATFNAME(Stat), EStatOperation::SpecialMessageMarker, FName(Value));\
385}
386#define STAT_ADD_CUSTOMMESSAGE_PTR(Stat,Value) \
387{\
388 FThreadStats::AddMessage(GET_STATFNAME(Stat), EStatOperation::SpecialMessageMarker, uint64(Value));\
389}
390
391#define SET_CYCLE_COUNTER_FName(Stat,Cycles) \
392{\
393 FThreadStats::AddMessage(Stat, EStatOperation::Set, int64(Cycles), true);\
394}
395
396#define INC_DWORD_STAT_FName(Stat) \
397{\
398 FThreadStats::AddMessage(Stat, EStatOperation::Add, int64(1));\
399}
400#define INC_FLOAT_STAT_BY_FName(Stat, Amount) \
401{\
402 double AddAmount = double(Amount); \
403 if (AddAmount != 0.0) \
404 { \
405 FThreadStats::AddMessage(Stat, EStatOperation::Add, AddAmount); \
406 } \
407}
408#define INC_DWORD_STAT_BY_FName(Stat, Amount) \
409{\
410 int64 AddAmount = int64(Amount); \
411 if (AddAmount != 0) \
412 { \
413 FThreadStats::AddMessage(Stat, EStatOperation::Add, AddAmount); \
414 } \
415}
416#define INC_DWORD_STAT_FNAME_BY(Stat, Amount) INC_DWORD_STAT_BY_FName(Stat, Amount)
417#define INC_MEMORY_STAT_BY_FName(Stat, Amount) \
418{\
419 int64 AddAmount = int64(Amount); \
420 if (AddAmount != 0) \
421 { \
422 FThreadStats::AddMessage(Stat, EStatOperation::Add, AddAmount); \
423 } \
424}
425#define DEC_DWORD_STAT_FName(Stat) \
426{\
427 FThreadStats::AddMessage(Stat, EStatOperation::Subtract, int64(1));\
428}
429#define DEC_FLOAT_STAT_BY_FName(Stat,Amount) \
430{\
431 double SubtractAmount = double(Amount); \
432 if (SubtractAmount != 0.0) \
433 { \
434 FThreadStats::AddMessage(Stat, EStatOperation::Subtract, SubtractAmount); \
435 } \
436}
437#define DEC_DWORD_STAT_BY_FName(Stat,Amount) \
438{\
439 int64 SubtractAmount = int64(Amount); \
440 if (SubtractAmount != 0) \
441 { \
442 FThreadStats::AddMessage(Stat, EStatOperation::Subtract, SubtractAmount); \
443 } \
444}
445#define DEC_DWORD_STAT_FNAME_BY(Stat,Amount) DEC_DWORD_STAT_BY_FName(Stat,Amount)
446#define DEC_MEMORY_STAT_BY_FName(Stat,Amount) \
447{\
448 int64 SubtractAmount = int64(Amount); \
449 if (SubtractAmount != 0) \
450 { \
451 FThreadStats::AddMessage(Stat, EStatOperation::Subtract, SubtractAmount); \
452 } \
453}
454#define SET_MEMORY_STAT_FName(Stat,Value) \
455{\
456 int64 SetValue = int64(Value); \
457 FThreadStats::AddMessage(Stat, EStatOperation::Set, SetValue); \
458}
459#define SET_DWORD_STAT_FName(Stat,Value) \
460{\
461 int64 SetValue = int64(Value); \
462 FThreadStats::AddMessage(Stat, EStatOperation::Set, SetValue); \
463}
464#define SET_FLOAT_STAT_FName(Stat,Value) \
465{\
466 double SetValue = double(Value); \
467 FThreadStats::AddMessage(Stat, EStatOperation::Set, SetValue); \
468}
469
470#elif UE_USE_LIGHTWEIGHT_STATS // STATS
471// STATS == 0
472
473// ----------------------------------------------------------------------------
474// Lightweight Stats
475// ----------------------------------------------------------------------------
476// This defines a simpler and lower overhead version of the stat macros.
477// These will not emit any data to the runtime stat system and only emit
478// profiling namedevents if enabled.
479// ----------------------------------------------------------------------------
480
481// ----------------------------------------------------------------
482// Group Declarations
483// ----------------------------------------------------------------
484
485#define DECLARE_STAT_GROUP(GroupId, CompiledIn) \
486 struct FStatGroup_##GroupId\
487 {\
488 static constexpr const PROFILER_CHAR* GetName()\
489 {\
490 return ANSI_TO_PROFILING(#GroupId);\
491 }\
492 static constexpr uint32 GetNameHash()\
493 {\
494 return UE_STATS_HASH_NAME(GroupId);\
495 }\
496 static constexpr bool IsCompileTimeEnable()\
497 {\
498 return CompiledIn;\
499 }\
500 };
501
502#define DECLARE_STATS_GROUP(GroupDesc, GroupId, GroupCat) \
503 DECLARE_STAT_GROUP(GroupId, true);
504
505#define DECLARE_STATS_GROUP_SORTBYNAME(GroupDesc, GroupId, GroupCat) \
506 DECLARE_STAT_GROUP(GroupId, true);
507
508#define DECLARE_STATS_GROUP_VERBOSE(GroupDesc, GroupId, GroupCat) \
509 DECLARE_STAT_GROUP(GroupId, true);
510
511#define DECLARE_STATS_GROUP_MAYBE_COMPILED_OUT(GroupDesc, GroupId, GroupCat, CompileIn) \
512 DECLARE_STAT_GROUP(GroupId, static_cast<bool>(CompileIn));
513
514// ----------------------------------------------------------------
515// Stat Declarations
516// ----------------------------------------------------------------
517
518#define DECLARE_STAT(StatName, GroupName, StatFlags)\
519 struct FStat_##StatName\
520 {\
521 using TGroup = UE_INTERNAL_GET_STATGROUP_TYPE(GroupName);\
522 static constexpr const PROFILER_CHAR* GetName()\
523 {\
524 return ANSI_TO_PROFILING(#StatName);\
525 }\
526 static constexpr EStatFlags GetFlags()\
527 {\
528 return StatFlags;\
529 }\
530 };
531
532// Replace declarations with lightweight instances
533#define DECLARE_CYCLE_STAT(CounterName, StatId, GroupId) \
534 DECLARE_STAT(StatId, GroupId, EStatFlags::None);
535
536#define DECLARE_CYCLE_STAT_WITH_FLAGS(CounterName, StatId, GroupId, StatFlags) \
537 DECLARE_STAT(StatId, GroupId, StatFlags);
538
539#define DECLARE_CYCLE_STAT_EXTERN(CounterName, StatId, GroupId, APIX) \
540 DECLARE_STAT(StatId, GroupId, EStatFlags::None);
541
542#define DECLARE_CYCLE_STAT_WITH_FLAGS_EXTERN(CounterName, StatId, GroupId, StatFlags, APIX) \
543 DECLARE_STAT(StatId, GroupId, StatFlags);
544
545#define DECLARE_MEMORY_STAT_EXTERN(CounterName, StatId, GroupId, API)\
546 DECLARE_STAT(StatId, GroupId, EStatFlags::None);
547
548#define DECLARE_MEMORY_STAT_POOL_EXTERN(CounterName, StatId, GroupId, Pool, API)\
549 DECLARE_STAT(StatId, GroupId, EStatFlags::None);
550
551#define DECLARE_MEMORY_STAT(CounterName,StatId,GroupId)\
552 DECLARE_STAT(StatId, GroupId, EStatFlags::None);
553
554#define DECLARE_MEMORY_STAT_POOL(CounterName,StatId,GroupId,Pool)\
555 DECLARE_STAT(StatId, GroupId, EStatFlags::None);
556
557// Some systems like the GPU profiler utilize counter declarations to declare stats used with SCOPE_CYCLE_COUNTER.
558// Since this is a special case, allow falling back to the default stat data for these.
559#define DECLARE_FLOAT_COUNTER_STAT(CounterName,StatId,GroupId) UE_INTERNAL_ALLOW_DEFAULT_STAT(StatId);
560#define DECLARE_FLOAT_COUNTER_STAT_EXTERN(CounterName,StatId,GroupId, API) UE_INTERNAL_ALLOW_DEFAULT_STAT(StatId);
561#define DECLARE_FLOAT_ACCUMULATOR_STAT(CounterName,StatId,GroupId) UE_INTERNAL_ALLOW_DEFAULT_STAT(StatId);
562#define DECLARE_FLOAT_ACCUMULATOR_STAT_EXTERN(CounterName,StatId,GroupId, API) UE_INTERNAL_ALLOW_DEFAULT_STAT(StatId);
563#define DECLARE_DWORD_COUNTER_STAT(CounterName,StatId,GroupId) UE_INTERNAL_ALLOW_DEFAULT_STAT(StatId);
564#define DECLARE_DWORD_COUNTER_STAT_EXTERN(CounterName,StatId,GroupId, API) UE_INTERNAL_ALLOW_DEFAULT_STAT(StatId);
565#define DECLARE_DWORD_ACCUMULATOR_STAT(CounterName,StatId,GroupId) UE_INTERNAL_ALLOW_DEFAULT_STAT(StatId);
566#define DECLARE_DWORD_ACCUMULATOR_STAT_EXTERN(CounterName,StatId,GroupId, API) UE_INTERNAL_ALLOW_DEFAULT_STAT(StatId);
567#define DECLARE_FNAME_STAT(CounterName,StatId,GroupId, API) UE_INTERNAL_ALLOW_DEFAULT_STAT(StatId);
568#define DECLARE_PTR_STAT(CounterName,StatId,GroupId) UE_INTERNAL_ALLOW_DEFAULT_STAT(StatId);
569#define DECLARE_FNAME_STAT_EXTERN(CounterName,StatId,GroupId, API) UE_INTERNAL_ALLOW_DEFAULT_STAT(StatId);
570#define DECLARE_PTR_STAT_EXTERN(CounterName,StatId,GroupId, API) UE_INTERNAL_ALLOW_DEFAULT_STAT(StatId);
571
572// ----------------------------------------------------------------
573// Scope Counters
574// ----------------------------------------------------------------
575
576#define SCOPE_CYCLE_COUNTER_TO_TRACE(StatString, StatName, Condition) \
577 TRACE_CPUPROFILER_EVENT_DECLARE(PREPROCESSOR_JOIN(PREPROCESSOR_JOIN(__Decl_, StatName), __LINE__)); \
578 TRACE_CPUPROFILER_EVENT_SCOPE_USE(PREPROCESSOR_JOIN(PREPROCESSOR_JOIN(__Decl_, StatName), __LINE__), StatString, PREPROCESSOR_JOIN(PREPROCESSOR_JOIN(__Scope_, StatName), __LINE__), Condition && GCycleStatsShouldEmitNamedEvents);
579
580// Note: Since these are defining the stat inline, no custom stat data will exist.
581#define DECLARE_SCOPE_CYCLE_COUNTER(CounterName,Stat,GroupId) \
582 const UE::Stats::Private::FCheckedStat Stat_##Stat = UE_INTERNAL_GET_QUICK_STAT_WITH_GROUP_IF_ENABLED(Stat, GroupId);\
583 UE::Stats::Private::FScopeCycleCounterStatic StatNamedEventsScope_##Stat(Stat_##Stat); \
584 SCOPE_CYCLE_COUNTER_TO_TRACE(CounterName, Stat, Stat_##Stat.IsValidStat());
585
586#define QUICK_SCOPE_CYCLE_COUNTER(Stat) \
587 const UE::Stats::Private::FCheckedStat Stat_##Stat = UE_INTERNAL_GET_QUICK_STAT_IF_ENABLED(Stat);\
588 UE::Stats::Private::FScopeCycleCounterStatic StatNamedEventsScope_##Stat(Stat_##Stat); \
589 SCOPE_CYCLE_COUNTER_TO_TRACE(#Stat, Stat, Stat_##Stat.IsValidStat());
590
591// Note: FScopeCycleCounter is what emits the trace events to external profilers
592// while SCOPE_CYCLE_COUNTER_TO_TRACE handles emitting it to insights.
593// FScopeCycleCounter handles verbosity checks itself.
594#define SCOPE_CYCLE_COUNTER(Stat) \
595 const UE::Stats::Private::FCheckedStat Stat_##Stat = UE_INTERNAL_GET_STAT_IF_ENABLED(Stat);\
596 UE::Stats::Private::FScopeCycleCounterStatic StatNamedEventsScope_##Stat(Stat_##Stat); \
597 SCOPE_CYCLE_COUNTER_TO_TRACE(#Stat, Stat, Stat_##Stat.IsValidStat());
598
599// NOTE: This macro bypasses the standard enable checks as we don't know the stat's type/group.
600#define SCOPE_CYCLE_COUNTER_STATID(StatId) \
601 FScopeCycleCounter StatNamedEventsScope_STATID(StatId); \
602 TRACE_CPUPROFILER_EVENT_SCOPE_TEXT_CONDITIONAL(StatId.StatString, StatId.IsValidStat() && GCycleStatsShouldEmitNamedEvents > 0);
603
604#define CONDITIONAL_SCOPE_CYCLE_COUNTER(Stat,bCondition) \
605 const UE::Stats::Private::FCheckedStat Stat_##Stat = UE_INTERNAL_GET_STAT_IF_ENABLED_COND(Stat, static_cast<bool>(bCondition));\
606 UE::Stats::Private::FScopeCycleCounterStatic StatNamedEventsScope_##Stat(Stat_##Stat); \
607 SCOPE_CYCLE_COUNTER_TO_TRACE(#Stat, Stat, Stat_##Stat.IsValidStat());
608
609#define RETURN_QUICK_DECLARE_CYCLE_STAT(StatId,GroupId) return QUICK_USE_CYCLE_STAT(StatId, GroupId);
610
611#define QUICK_USE_CYCLE_STAT(StatId,GroupId) UE_INTERNAL_GET_QUICK_STAT_WITH_GROUP_IF_ENABLED(StatId, GroupId)
612
613#define GET_STATID(Stat) UE_INTERNAL_GET_STAT_IF_ENABLED(Stat)
614
615#elif USE_LIGHTWEIGHT_STATS_FOR_HITCH_DETECTION && USE_HITCH_DETECTION
616// STATS == 0
617// UE_USE_LIGHTWEIGHT_STATS == 0
618
619// ----------------------------------------------------------------------------
620// Hitch Detection
621// ----------------------------------------------------------------------------
622// This replaces the stat macros with a very lightweight scoped struct to create
623// a rough approximation of the current callstack for hitch tracking purposes.
624// This let's us avoid traversing the actual callstack at runtime during a hitch which is very slow.
625// ----------------------------------------------------------------------------
626
627#define DECLARE_SCOPE_CYCLE_COUNTER(CounterName,Stat,GroupId) \
628 UE::Stats::FHitchTrackingStatScope HitchTrackingStatScope_##Stat(ANSI_TO_PROFILING(#Stat));
629
630#define QUICK_SCOPE_CYCLE_COUNTER(Stat) \
631 UE::Stats::FHitchTrackingStatScope HitchTrackingStatScope_##Stat(ANSI_TO_PROFILING(#Stat));
632
633#define SCOPE_CYCLE_COUNTER(Stat) \
634 UE::Stats::FHitchTrackingStatScope HitchTrackingStatScope_##Stat(ANSI_TO_PROFILING(#Stat));
635
636#define SCOPE_CYCLE_COUNTER_STATID(StatId) \
637 UE::Stats::FHitchTrackingStatScope HitchTrackingStatScope_##Stat(ANSI_TO_PROFILING("Lightweight StatId Scope"));
638
639#define CONDITIONAL_SCOPE_CYCLE_COUNTER(Stat,bCondition) \
640 UE::Stats::FHitchTrackingStatScope HitchTrackingStatScope_##Stat(bCondition ? ANSI_TO_PROFILING(#Stat) : nullptr);
641
642#define RETURN_QUICK_DECLARE_CYCLE_STAT(StatId,GroupId) return TStatId();
643#define GET_STATID(Stat) (TStatId())
644
645#else
646// STATS == 0
647// UE_USE_LIGHTWEIGHT_STATS == 0
648// (USE_LIGHTWEIGHT_STATS_FOR_HITCH_DETECTION && USE_HITCH_DETECTION) == 0
649
650#define SCOPE_CYCLE_COUNTER(Stat)
651#define SCOPE_CYCLE_COUNTER_STATID(StatId)
652#define QUICK_SCOPE_CYCLE_COUNTER(Stat)
653#define DECLARE_SCOPE_CYCLE_COUNTER(CounterName,StatId,GroupId)
654#define CONDITIONAL_SCOPE_CYCLE_COUNTER(Stat,bCondition)
655#define RETURN_QUICK_DECLARE_CYCLE_STAT(StatId,GroupId) return TStatId();
656#define GET_STATID(Stat) (TStatId())
657#endif // STATS
658
659// ----------------------------------------------------------------------------
660// Default Macro Definitions
661// ----------------------------------------------------------------------------
662#if !STATS
663#define SCOPE_SECONDS_ACCUMULATOR(Stat)
664#define SCOPE_MS_ACCUMULATOR(Stat)
665#define DEFINE_STAT(Stat)
666
667#if !UE_USE_LIGHTWEIGHT_STATS
668#define QUICK_USE_CYCLE_STAT(StatId,GroupId) TStatId()
669#define DECLARE_CYCLE_STAT(CounterName,StatId,GroupId)
670#define DECLARE_CYCLE_STAT_WITH_FLAGS(CounterName,StatId,GroupId,StatFlags)
671#define DECLARE_FLOAT_COUNTER_STAT(CounterName,StatId,GroupId)
672#define DECLARE_DWORD_COUNTER_STAT(CounterName,StatId,GroupId)
673#define DECLARE_FLOAT_ACCUMULATOR_STAT(CounterName,StatId,GroupId)
674#define DECLARE_DWORD_ACCUMULATOR_STAT(CounterName,StatId,GroupId)
675#define DECLARE_FNAME_STAT(CounterName,StatId,GroupId, API)
676#define DECLARE_PTR_STAT(CounterName,StatId,GroupId)
677#define DECLARE_MEMORY_STAT(CounterName,StatId,GroupId)
678#define DECLARE_MEMORY_STAT_POOL(CounterName,StatId,GroupId,Pool)
679#define DECLARE_CYCLE_STAT_EXTERN(CounterName,StatId,GroupId, API)
680#define DECLARE_CYCLE_STAT_WITH_FLAGS_EXTERN(CounterName,StatId,GroupId,StatFlags, API)
681#define DECLARE_FLOAT_COUNTER_STAT_EXTERN(CounterName,StatId,GroupId, API)
682#define DECLARE_DWORD_COUNTER_STAT_EXTERN(CounterName,StatId,GroupId, API)
683#define DECLARE_FLOAT_ACCUMULATOR_STAT_EXTERN(CounterName,StatId,GroupId, API)
684#define DECLARE_DWORD_ACCUMULATOR_STAT_EXTERN(CounterName,StatId,GroupId, API)
685#define DECLARE_FNAME_STAT_EXTERN(CounterName,StatId,GroupId, API)
686#define DECLARE_PTR_STAT_EXTERN(CounterName,StatId,GroupId, API)
687#define DECLARE_MEMORY_STAT_EXTERN(CounterName,StatId,GroupId, API)
688#define DECLARE_MEMORY_STAT_POOL_EXTERN(CounterName,StatId,GroupId,Pool, API)
689#define DECLARE_STATS_GROUP(GroupDesc,GroupId,GroupCat)
690#define DECLARE_STATS_GROUP_VERBOSE(GroupDesc,GroupId,GroupCat)
691#define DECLARE_STATS_GROUP_SORTBYNAME(GroupDesc,GroupId,GroupCat)
692#define DECLARE_STATS_GROUP_MAYBE_COMPILED_OUT(GroupDesc,GroupId,GroupCat,CompileIn)
693#endif // !UE_USE_LIGHTWEIGHT_STATS
694
695#define SET_CYCLE_COUNTER(Stat,Cycles)
696#define INC_DWORD_STAT(StatId)
697#define INC_FLOAT_STAT_BY(StatId,Amount)
698#define INC_DWORD_STAT_BY(StatId,Amount)
699#define INC_DWORD_STAT_FNAME_BY(StatId,Amount)
700#define INC_MEMORY_STAT_BY(StatId,Amount)
701#define DEC_DWORD_STAT(StatId)
702#define DEC_FLOAT_STAT_BY(StatId,Amount)
703#define DEC_DWORD_STAT_BY(StatId,Amount)
704#define DEC_DWORD_STAT_FNAME_BY(StatId,Amount)
705#define DEC_MEMORY_STAT_BY(StatId,Amount)
706#define SET_MEMORY_STAT(StatId,Value)
707#define SET_DWORD_STAT(StatId,Value)
708#define SET_FLOAT_STAT(StatId,Value)
709#define STAT_ADD_CUSTOMMESSAGE_NAME(StatId,Value)
710#define STAT_ADD_CUSTOMMESSAGE_PTR(StatId,Value)
711
712#define SET_CYCLE_COUNTER_FName(Stat,Cycles)
713#define INC_DWORD_STAT_FName(Stat)
714#define INC_FLOAT_STAT_BY_FName(Stat, Amount)
715#define INC_DWORD_STAT_BY_FName(Stat, Amount)
716#define INC_MEMORY_STAT_BY_FName(Stat, Amount)
717#define DEC_DWORD_STAT_FName(Stat)
718#define DEC_FLOAT_STAT_BY_FName(Stat,Amount)
719#define DEC_DWORD_STAT_BY_FName(Stat,Amount)
720#define DEC_MEMORY_STAT_BY_FName(Stat,Amount)
721#define SET_MEMORY_STAT_FName(Stat,Value)
722#define SET_DWORD_STAT_FName(Stat,Value)
723#define SET_FLOAT_STAT_FName(Stat,Value)
724
725#define GET_STATFNAME(Stat) (FName())
726#define GET_STATDESCRIPTION(Stat) (nullptr)
727#endif // !STATS
728
729#include "Stats/GlobalStats.inl"
730
731// Deprecated includes from Stats2.h
732#if UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_6
733// These should be included directly instead of through this header.
735#include "Stats/StatsCommand.h"
736#include "Stats/StatsSystem.h"
739
740// Includes from Stats2.h
741#include "Containers/Array.h"
746#include "CoreGlobals.h"
747#include "CoreTypes.h"
748#include "Delegates/Delegate.h"
750#include "HAL/CriticalSection.h"
752#include "HAL/PlatformCrt.h"
753#include "HAL/PlatformMemory.h"
754#include "HAL/PlatformMisc.h"
755#include "HAL/PlatformTLS.h"
756#include "HAL/PlatformTime.h"
758#include "HAL/ThreadSingleton.h"
759#include "HAL/UnrealMemory.h"
760#include "Math/Color.h"
761#include "Math/NumericLimits.h"
762#include "Misc/AssertionMacros.h"
763#include "Misc/Build.h"
764#include "Misc/CString.h"
765#include "Misc/EnumClassFlags.h"
768#include "StatsCommon.h"
769#include "StatsTrace.h"
770#include "Templates/Atomic.h"
772#include "Templates/UniquePtr.h"
774#include "Trace/Detail/Channel.h"
776#include "Trace/Trace.h"
777#include "UObject/NameTypes.h"
778#include "UObject/UnrealNames.h"
779#endif // UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_6
EStatType
Definition Stats.h:31
@ STATTYPE_CounterDWORD
Definition Stats.h:36
@ STATTYPE_CounterFLOAT
Definition Stats.h:35
@ STATTYPE_AccumulatorFLOAT
Definition Stats.h:33
@ STATTYPE_MemoryCounter
Definition Stats.h:37
@ STATTYPE_Error
Definition Stats.h:38
@ STATTYPE_AccumulatorDWORD
Definition Stats.h:34
@ STATTYPE_CycleCounter
Definition Stats.h:32