UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
CookStats.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "Containers/Array.h"
8#include "CoreGlobals.h"
9#include "CoreTypes.h"
10#include "Delegates/Delegate.h"
11#include "HAL/PlatformTime.h"
14#include "Templates/Decay.h"
15#include "Templates/Function.h"
17#include "Trace/Trace.h"
18
19namespace UE { namespace Trace { class FChannel; } }
20
21#ifndef ENABLE_COOK_STATS
22#define ENABLE_COOK_STATS WITH_EDITOR
23#endif
24
25template <typename FuncType> class TFunctionRef;
26template <typename T> struct TDecay;
27
35
36#if ENABLE_COOK_STATS
57{
58public:
63 template <typename KeyType, typename ValueType>
64 struct TKeyValuePair
65 {
66 template<typename KeyType2, typename ValueType2>
69 {
70 }
71 TKeyValuePair() : Key {}, Value {}
72 {
73 }
74 bool operator==(const TKeyValuePair& Other) const
75 {
76 return Key == Other.Key;
77 }
78 bool operator!=(const TKeyValuePair& Other) const
79 {
80 return Key != Other.Key;
81 }
82 bool operator<(const TKeyValuePair& Other) const
83 {
84 return Key < Other.Key;
85 }
86 UE_FORCEINLINE_HINT bool operator()(const TKeyValuePair& A, const TKeyValuePair& B) const
87 {
88 return A.Key < B.Key;
89 }
90 KeyType Key;
91 ValueType Value;
92 };
93
95 template <typename KeyType, typename ValueType>
97 {
99 }
100
101
105 typedef TFunctionRef<void(const FString& StatName, const TArray<StringKeyValue>& StatAttributes)> AddStatFuncRef;
106
109
112
115
118 {
119 template<typename Func>
120 explicit FAutoRegisterCallback(Func Callback)
121 {
122 CookStatsCallbacks.AddLambda(Callback);
123 }
124 };
125
126 //-------------------------------------------------------------------------
127 // Helper to initialize an array of KeyValues on one line.
128 //-------------------------------------------------------------------------
129
131 template <typename...ArgTypes>
133 {
135 Attrs.Empty(sizeof...(Args) / 2);
137 return Attrs;
138 }
139
140private:
141 template <typename KeyType>
143 {
144 Attrs.Emplace(LexToString(Forward<KeyType>(Key)), TEXT(""));
145 }
146
147 template <typename KeyType, typename ValueType>
148 static void ImplCreateKeyValueArray(TArray<FCookStatsManager::StringKeyValue>& Attrs, KeyType&& Key, ValueType&& Value)
149 {
151 }
152
153 template <typename KeyType, typename ValueType, typename...ArgTypes>
154 static void ImplCreateKeyValueArray(TArray<FCookStatsManager::StringKeyValue>& Attrs, KeyType&& Key, ValueType&& Value, ArgTypes&&...Args)
155 {
158 }
159
160};
161
163
169class FCookStats
170{
171public:
182 struct CallStats
183 {
185 enum class EHitOrMiss : uint8
186 {
187 Hit,
188 Miss,
189 MaxValue,
190 };
191
193 enum class EStatType : uint8
194 {
195 Counter,
196 Cycles,
197 Bytes,
198 MaxValue,
199 };
200
203 {
205 void Accumulate(int64 Value, bool bIsInGameThread)
206 {
207 if (bIsInGameThread)
208 {
209 GameThread += Value;
210 }
211 else if (Value != 0)
212 {
213 OtherThread.Add(Value);
214 }
215 }
217 int64 GetAccumulatedValue(bool bIsInGameThread) const
218 {
219 return bIsInGameThread ? GameThread : OtherThread.GetValue();
220 }
221
222 int64 GameThread = 0l;
224 };
225
227 void Accumulate(EHitOrMiss HitOrMiss, EStatType StatType, int64 Value, bool bIsInGameThread)
228 {
229 Accumulators[(uint8)HitOrMiss][(uint8)StatType].Accumulate(Value, bIsInGameThread);
230 }
231
233 int64 GetAccumulatedValue(EHitOrMiss HitOrMiss, EStatType StatType, bool bIsInGameThread) const
234 {
235 return Accumulators[(uint8)HitOrMiss][(uint8)StatType].GetAccumulatedValue(bIsInGameThread);
236 }
237
240 {
242 }
243
245 void LogStats(FCookStatsManager::AddStatFuncRef AddStat, const FString& StatName, const FString& NodeName, const TCHAR* CallName) const
246 {
247 auto LogStat = [&](EHitOrMiss HitOrMiss, bool bGameThread)
248 {
249 // only report the stat if it's non-zero
250 if (GetAccumulatedValue(HitOrMiss, EStatType::Cycles, bGameThread) > 0)
251 {
252 AddStat(StatName, FCookStatsManager::CreateKeyValueArray(
253 TEXT("ThreadName"), bGameThread ? TEXT("GameThread") : TEXT("OthrThread"),
254 TEXT("Call"), CallName,
255 TEXT("HitOrMiss"), HitOrMiss == EHitOrMiss::Hit ? TEXT("Hit") : TEXT("Miss"),
257 TEXT("TimeSec"), (double)GetAccumulatedValue(HitOrMiss, EStatType::Cycles, bGameThread) * FPlatformTime::GetSecondsPerCycle(),
258 TEXT("MB"), (double)GetAccumulatedValue(HitOrMiss, EStatType::Bytes, bGameThread) / (1024.0 * 1024.0),
260 ? 0.0
262 ((double)GetAccumulatedValue(HitOrMiss, EStatType::Cycles, bGameThread) * FPlatformTime::GetSecondsPerCycle()),
263 TEXT("Node"), NodeName
264 ));
265 }
266 };
267
268 LogStat(EHitOrMiss::Hit, true);
269 LogStat(EHitOrMiss::Miss, true);
270 LogStat(EHitOrMiss::Hit, false);
271 LogStat(EHitOrMiss::Miss, false);
272 }
273
274 void Combine(const CallStats& Other)
275 {
277 {
278 for (int32 HitOrMiss = 0; HitOrMiss < (uint8)EHitOrMiss::MaxValue; HitOrMiss++)
279 {
280 for (int32 StatType = 0; StatType < (uint8)EStatType::MaxValue; StatType++)
281 {
282 int64 Value = Other.GetAccumulatedValue((EHitOrMiss)HitOrMiss, (EStatType)StatType, IsGameThread == 1);
284 }
285 }
286 }
287 }
288
289 private:
291 GameAndOtherThreadAccumulator Accumulators[(uint8)EHitOrMiss::MaxValue][(uint8)EStatType::MaxValue];
292 };
293
300 {
301 public:
304 : Stats(InStats)
305 , StartTime(FPlatformTime::Cycles64())
306 , bIsInGameThread(IsInGameThread())
307 {
308 }
309
311 : Stats(InOther.Stats)
312 , StartTime(InOther.StartTime)
313 , BytesProcessed(InOther.BytesProcessed)
314 , bIsInGameThread(InOther.bIsInGameThread)
315 , bCanceled(InOther.bCanceled)
318 {
319 InOther.Cancel();
320 }
321
323
326 {
327 if (!bCanceled)
328 {
329 uint64 CurrentTime = FPlatformTime::Cycles64();
330 const uint64 CyclesUsed = CurrentTime - StartTime;
331
332 Stats.Accumulate(HitOrMiss, CallStats::EStatType::Cycles, CyclesUsed, bIsInGameThread);
333 if (!bTrackCyclesOnly)
334 {
335 Stats.Accumulate(HitOrMiss, CallStats::EStatType::Counter, 1l, bIsInGameThread);
336 }
337 Stats.Accumulate(HitOrMiss, CallStats::EStatType::Bytes, BytesProcessed, bIsInGameThread);
338 }
339 }
340
341 public:
343 void AddHit(int64 InBytesProcessed)
344 {
345 HitOrMiss = CallStats::EHitOrMiss::Hit;
346 BytesProcessed = InBytesProcessed;
347 }
348
351 {
352 HitOrMiss = CallStats::EHitOrMiss::Miss;
353 BytesProcessed = InBytesProcessed;
354 }
355
357 void AddHitOrMiss(CallStats::EHitOrMiss InHitOrMiss, int64 InBytesProcessed)
358 {
360 BytesProcessed = InBytesProcessed;
361 }
362
364 void Cancel()
365 {
366 bCanceled = true;
367 }
368
370 void TrackCyclesOnly()
371 {
372 bTrackCyclesOnly = true;
373 }
374
375 private:
376 CallStats& Stats;
377 uint64 StartTime;
378 int64 BytesProcessed = 0;
379 bool bIsInGameThread;
380 bool bCanceled = false;
381 bool bTrackCyclesOnly = false;
382 CallStats::EHitOrMiss HitOrMiss = CallStats::EHitOrMiss::Miss;
383 };
384
386};
387
414{
416 FCookStats::FScopedStatsCounter TimeSyncWork()
417 {
418 return FCookStats::FScopedStatsCounter(SyncWorkStats);
419 }
420
422 FCookStats::FScopedStatsCounter TimeAsyncWait()
423 {
424 return FCookStats::FScopedStatsCounter(AsyncWaitStats);
425 }
426
427 // expose these publicly for low level access. These should really never be accessed directly except when finished accumulating them.
428 FCookStats::CallStats SyncWorkStats;
429 FCookStats::CallStats AsyncWaitStats;
430
431 void LogStats(FCookStatsManager::AddStatFuncRef AddStat, const FString& StatName, const FString& NodeName) const
432 {
433 SyncWorkStats.LogStats(AddStat, StatName, NodeName, TEXT("SyncWork"));
434 AsyncWaitStats.LogStats(AddStat, StatName, NodeName, TEXT("AsyncWait"));
435 }
436};
437
439#define COOK_STAT(...) __VA_ARGS__
440
442
443#define UE_INSIGHTS_COOK_PROFILER_VERSION 2
444
445CORE_API void TracePackage(uint64 InId, const FStringView InName);
448
449#if UE_INSIGHTS_COOK_PROFILER_VERSION == 2
450
451UE_DEPRECATED(5.5, "TracePackageStat is deprecated, please use TracePackageStatBeginScope and TracePackageStatEndScope instead.")
453
456
458{
459 FScopedCookStat(const FScopedCookStat&) = delete;
461
463 : Id(Id)
465 {
467 }
468
470 {
472 }
473
474private:
475 uint64 Id;
477};
478
479#endif
480
481#if UE_INSIGHTS_COOK_PROFILER_VERSION == 1
482
483UE_DEPRECATED(5.5, "TracePackageStat is deprecated, please use TracePackageStatBeginScope and TracePackageStatEndScope instead.")
485
487{
488 FScopedCookStat(const FScopedCookStat&) = delete;
490
492 : Id(Id)
494 {
495 StartTimestamp = FPlatformTime::Cycles64();
496 }
497
499 {
500 uint64 Duration = FPlatformTime::Cycles64() - StartTimestamp;
502 }
503
504private:
505 uint64 Id;
506 uint64 StartTimestamp;
508};
509
510#endif
511
512#define UE_SCOPED_COOK_STAT(Name, StatType) \
513 FScopedCookStat PREPROCESSOR_JOIN(__CookTimerScope, __LINE__)(Name.ToUnstableInt(), StatType);
514
515#define UE_MULTI_SCOPED_COOK_STAT_INIT() \
516 TOptional<FScopedCookStat> __CookStatScope; \
517 FName __PrevPackageName = NAME_None;
518
519#define UE_MULTI_SCOPED_COOK_STAT(Name, StatType) \
520 if (__PrevPackageName != Name) \
521 { \
522 __CookStatScope.Emplace(Name.ToUnstableInt(), EPackageEventStatType::LoadPackage); \
523 __PrevPackageName = Name; \
524 }
525
526#define UE_MULTI_SCOPED_COOK_STAT_RESET() \
527 __CookStatScope.Reset(); \
528 __PrevPackageName = NAME_None;
529#else
530
531#define COOK_STAT(...)
532#define UE_SCOPED_COOK_STAT(...)
533#define UE_MULTI_SCOPED_COOK_STAT_INIT(...)
534#define UE_MULTI_SCOPED_COOK_STAT(...)
535#define UE_MULTI_SCOPED_COOK_STAT_RESET(...)
536
537#define TracePackage(...)
538#define TracePackageStat(...)
539#define TracePackageStatBeginScope(...)
540#define TracePackageStatEndScope(...)
541#define TracePackageAssetClass(...)
542#define ShouldTracePackageInfo(...) false
543
544#endif
OODEFFUNC typedef void(OODLE_CALLBACK t_fp_OodleCore_Plugin_Free)(void *ptr)
#define TracePackageStatEndScope(...)
Definition CookStats.h:540
#define TracePackageStat(...)
Definition CookStats.h:538
EPackageEventStatType
Definition CookStats.h:29
#define ShouldTracePackageInfo(...)
Definition CookStats.h:542
#define TracePackageStatBeginScope(...)
Definition CookStats.h:539
#define TracePackage(...)
Definition CookStats.h:537
#define TracePackageAssetClass(...)
Definition CookStats.h:541
#define UE_DEPRECATED(Version, Message)
Definition CoreMiscDefines.h:302
#define TEXT(x)
Definition Platform.h:1272
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
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define UE_FORCEINLINE_HINT
Definition Platform.h:723
FPlatformTypes::uint64 uint64
A 64-bit unsigned integer.
Definition Platform.h:1117
EStatType
Definition Stats.h:31
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
#define DECLARE_MULTICAST_DELEGATE_OneParam(DelegateName, Param1Type)
Definition DelegateCombinations.h:49
const TCHAR * LexToString(EAnalyticsRecordEventMode Mode)
Definition IAnalyticsProvider.cpp:5
bool operator<(const FTextFormatString &LHS, const FTextFormatString &RHS)
Definition ITextFormatArgumentModifier.h:147
UE_FORCEINLINE_HINT bool operator!=(const FIndexedPointer &Other) const
Definition LockFreeList.h:76
CORE_API bool IsInGameThread()
Definition ThreadingBase.cpp:185
#define UE_TRACE_CHANNEL_EXTERN(ChannelName,...)
Definition Trace.h:448
uint8_t uint8
Definition binka_ue_file_header.h:8
Definition ThreadSafeCounter64.h:14
Definition Array.h:670
void Empty(SizeType Slack=0)
Definition Array.h:2273
Definition AssetRegistryState.h:50
Pair< T1, T2 > MakePair(const T1 &First, const T2 &Second)
Definition Pair.h:45
@ Trace
Definition NetTraceConfig.h:23
constexpr int32 MaxValue
Definition LandscapeDataAccess.h:26
bool operator==(const FCachedAssetKey &A, const FCachedAssetKey &B)
Definition AssetDataMap.h:501
Definition AdvancedWidgetsModule.cpp:13
Definition AndroidPlatformTime.h:18
static uint64 Cycles64()
Definition AndroidPlatformTime.h:34
Definition Decay.h:44
UE::Core::Private::Decay::TDecayNonReference< typenameTRemoveReference< T >::Type >::Type Type
Definition Decay.h:45
Definition UnrealTemplate.h:462