UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
ReachabilityAnalysisState.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3/*=============================================================================
4 ReachabilityAnalysisState.h: Support for incremental reachability analysis
5=============================================================================*/
6
7#pragma once
8
9#include "CoreMinimal.h"
10#include "UObject/UObjectBase.h"
11#include "UObject/Object.h"
14
15namespace UE::GC
16{
17
22{
23public:
24
25 // Work-stealing algorithms are O(N^2), everyone steals from everyone.
26 // Might want to improve that before going much wider.
27 static constexpr int32 MaxWorkers = 16;
28
29private:
31 int32 NumWorkers = 0;
33 FWorkerContext* Contexts[MaxWorkers] = { nullptr };
34
36 EObjectFlags ObjectKeepFlags = RF_NoFlags;
38 bool bPerformFullPurge = false;
40 bool bIsSuspended = false;
43
45 double IncrementalMarkPhaseTotalTime = 0.0;
46
48 double ReferenceProcessingTotalTime = 0.0;
49
51 int32 NumIterations = 0;
52
54 int32 NumRechabilityIterationsToSkip = 0;
55
56 alignas (PLATFORM_CACHE_LINE_SIZE) double IterationStartTime = 0.0;
57 alignas (PLATFORM_CACHE_LINE_SIZE) double IterationTimeLimit = 0.0;
58
59public:
60
62
64 {
65 IterationTimeLimit = InTimeLimit;
66 IterationStartTime = FPlatformTime::Seconds();
67 }
68
70 {
71 return Stats;
72 }
73
74 bool IsSuspended() const
75 {
76 return bIsSuspended;
77 }
78
81
84
87 {
88 if (IterationTimeLimit > 0.0)
89 {
90 return (FPlatformTime::Seconds() - IterationStartTime) >= IterationTimeLimit;
91 }
92 return false;
93 }
94
96 {
97 return NumWorkers;
98 }
99
101 {
102 return Contexts;
103 }
104
106 {
107 return NumIterations;
108 }
109
111 void Init();
112
115
118
121
124
126 void ResetWorkers();
127
129 void FinishIteration();
130};
131
132
135{
136 None = 0,
137 Parallel = 1, // Use threading to increase performance
138};
140
141inline int32 GetNumThreadsForGather(const EGatherOptions Options, const int32 NumObjects)
142{
143 if (!!(Options & EGatherOptions::Parallel) && NumObjects > 0)
144 {
145 constexpr int32 MinNumObjectsPerThread = 100;
146 const int32 MaxNumThreads = FMath::Max(1, FTaskGraphInterface::Get().GetNumWorkerThreads());
148 return FMath::Min(NumThreadsForNumObjects, MaxNumThreads);
149 }
150 return 1;
151}
152
154template <typename PayloadType>
168
169template <typename PayloadType>
171{
172 inline static int32 Num(const PayloadType& InPayload)
173 {
174 return InPayload.Num();
175 }
176
177 inline static bool Reserve(const TArray<TGatherIterator<PayloadType>, TInlineAllocator<32>>& ThreadIterators, PayloadType& OutPayload)
178 {
180 for (const TGatherIterator<PayloadType>& It : ThreadIterators)
181 {
183 }
185 return SizeToReserve > 0;
186 }
187
188 inline static void Append(const PayloadType& InSource, PayloadType& OutDest)
189 {
190 OutDest.Append(InSource);
191 }
192};
193
195template <typename PayloadType, typename PayloadOps = TDefaultPayloadOps<PayloadType>>
197{
198public:
199
202
204 {
205 return ThreadIterators;
206 }
207
209 {
210 return ThreadIterators.Num() > 0;
211 }
212
214 {
215 return bIsPending;
216 }
217
218 void Init()
219 {
220 bIsPending = true;
221 }
222
223 FORCENOINLINE void Start(const EGatherOptions Options, const int32 TotalNumObjects, const int32 FirstIndex = 0, const int32 DesiredNumThreads = 0)
224 {
228
229 ThreadIterators.AddDefaulted(NumThreads);
230
231 for (int32 ThreadIndex = 0; ThreadIndex < NumThreads; ++ThreadIndex)
232 {
233 FIterator& Iterator = ThreadIterators[ThreadIndex];
234 Iterator.StartIndex = ThreadIndex * NumberOfObjectsPerThread + FirstIndex;
235 Iterator.Index = Iterator.StartIndex;
236 Iterator.Num = (ThreadIndex < (NumThreads - 1)) ? NumberOfObjectsPerThread : (TotalNumObjects - (NumThreads - 1) * NumberOfObjectsPerThread);
237 Iterator.LastIndex = FMath::Min(TotalNumObjects - 1, Iterator.Index + Iterator.Num - 1);
238 }
239 }
240
242 {
243 if (ThreadIterators.Num() == 1 && PayloadOps::Num(OutGatheredObjects) == 0)
244 {
245 OutGatheredObjects = MoveTemp(ThreadIterators[0].Payload);
246 }
247 else if (PayloadOps::Reserve(ThreadIterators, OutGatheredObjects))
248 {
249 for (FIterator& Iterator : ThreadIterators)
250 {
251 PayloadOps::Append(Iterator.Payload, OutGatheredObjects);
252 }
253 }
254 ThreadIterators.Reset();
255 bIsPending = false;
256 }
257
259 {
260 return ThreadIterators.Num();
261 }
262
264 {
265 int32 NumScanned = 0;
266 for (const FIterator& ThreadState : ThreadIterators)
267 {
268 NumScanned += ThreadState.Index - ThreadState.StartIndex;
269 }
270 return NumScanned;
271 }
272
274 {
275 int32 NumGathered = 0;
276 for (const FIterator& ThreadState : ThreadIterators)
277 {
278 NumGathered += PayloadOps::Num(ThreadState.Payload);
279 }
280 return NumGathered;
281 }
282
283private:
284
285 FThreadIterators ThreadIterators;
286 bool bIsPending = false;
287};
288
291{
292 const int32 TimeLimitPollInterval = 0;
293 int32 TimeLimitTimePollCounter = 0;
294 const double StartTime = 0.0;
295 const double TimeLimit = 0.0;
296 std::atomic<int32>& TimeLimitFlag;
297public:
298
300 : TimeLimitPollInterval(InPollInterval)
301 , TimeLimitTimePollCounter(InitialCounter)
302 , StartTime(InStartTime)
304 , TimeLimitFlag(InTimeLimitFlag)
305 {
306 }
307
309 {
310 if (TimeLimit > 0.0)
311 {
312 const bool bPollTimeLimit = ((TimeLimitTimePollCounter++) % TimeLimitPollInterval == 0);
313 if (bPollTimeLimit)
314 {
315 // It's this thread's time to check if time limit has been exceeded
316 if ((FPlatformTime::Seconds() - StartTime) >= TimeLimit)
317 {
318 TimeLimitFlag.store(1, std::memory_order_relaxed);
319 return true;
320 }
321 }
322 else
323 {
324 // Check if any other thread signaled that time limit has been exceeded
325 return !!TimeLimitFlag.load(std::memory_order_relaxed);
326 }
327 }
328 return false;
329 }
330};
331
332} // namespace UE::GC
333
334namespace UE::GC::Private
335{
342}
#define FORCENOINLINE
Definition AndroidPlatform.h:142
#define FORCEINLINE
Definition AndroidPlatform.h:140
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define PLATFORM_CACHE_LINE_SIZE
Definition Platform.h:938
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
#define ENUM_CLASS_FLAGS(Enum)
Definition EnumClassFlags.h:6
EObjectFlags
Definition ObjectMacros.h:552
@ RF_NoFlags
No flags, used to avoid a cast.
Definition ObjectMacros.h:555
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
uint32_t uint32
Definition binka_ue_file_header.h:6
static CORE_API FTaskGraphInterface & Get()
Definition TaskGraph.cpp:1794
Definition Array.h:670
UE_REWRITE SizeType Num() const
Definition Array.h:1144
void Reset(SizeType NewSize=0)
Definition Array.h:2246
SizeType AddDefaulted()
Definition Array.h:2795
Definition ContainerAllocationPolicies.h:894
Definition ReachabilityAnalysisState.h:22
bool IsSuspended() const
Definition ReachabilityAnalysisState.h:74
FORCEINLINE int32 GetNumWorkers() const
Definition ReachabilityAnalysisState.h:95
FORCEINLINE FWorkerContext ** GetContextArray()
Definition ReachabilityAnalysisState.h:100
void UpdateStats(const UE::GC::FProcessorStats &InStats)
Definition ReachabilityAnalysisState.cpp:29
void PerformReachabilityAnalysis()
Definition GarbageCollection.cpp:5981
FORCEINLINE bool IsTimeLimitExceeded() const
Definition ReachabilityAnalysisState.h:86
void Init()
Definition ReachabilityAnalysisState.cpp:17
void FinishIteration()
Definition ReachabilityAnalysisState.cpp:39
void CollectGarbage(EObjectFlags KeepFlags, bool bFullPurge)
Definition GarbageCollection.cpp:5816
FORCEINLINE int32 GetNumIterations() const
Definition ReachabilityAnalysisState.h:105
static constexpr int32 MaxWorkers
Definition ReachabilityAnalysisState.h:27
const UE::GC::FProcessorStats & GetStats() const
Definition ReachabilityAnalysisState.h:69
bool CheckIfAnyContextIsSuspended()
Definition ReachabilityAnalysisState.cpp:57
void SetupWorkers(int32 InNumWorkers)
Definition ReachabilityAnalysisState.cpp:22
void ResetWorkers()
Definition ReachabilityAnalysisState.cpp:34
void PerformReachabilityAnalysisAndConditionallyPurgeGarbage(bool bReachabilityUsingTimeLimit)
Definition GarbageCollection.cpp:5840
void StartTimer(double InTimeLimit)
Definition ReachabilityAnalysisState.h:63
Definition ReachabilityAnalysisState.h:291
FTimeSlicer(int32 InPollInterval, int32 InitialCounter, double InStartTime, double InTimeLimit, std::atomic< int32 > &InTimeLimitFlag)
Definition ReachabilityAnalysisState.h:299
FORCEINLINE bool IsTimeLimitExceeded()
Definition ReachabilityAnalysisState.h:308
Definition ReachabilityAnalysisState.h:197
FORCENOINLINE void Start(const EGatherOptions Options, const int32 TotalNumObjects, const int32 FirstIndex=0, const int32 DesiredNumThreads=0)
Definition ReachabilityAnalysisState.h:223
FORCEINLINE bool IsPending() const
Definition ReachabilityAnalysisState.h:213
FORCEINLINE bool IsSuspended() const
Definition ReachabilityAnalysisState.h:208
TGatherIterator< PayloadType > FIterator
Definition ReachabilityAnalysisState.h:200
FORCEINLINE FThreadIterators & GetThreadIterators()
Definition ReachabilityAnalysisState.h:203
int32 NumScanned() const
Definition ReachabilityAnalysisState.h:263
TArray< FIterator, TInlineAllocator< 32 > > FThreadIterators
Definition ReachabilityAnalysisState.h:201
FORCEINLINE int32 NumWorkerThreads() const
Definition ReachabilityAnalysisState.h:258
FORCENOINLINE void Finish(PayloadType &OutGatheredObjects)
Definition ReachabilityAnalysisState.h:241
int32 NumGathered() const
Definition ReachabilityAnalysisState.h:273
void Init()
Definition ReachabilityAnalysisState.h:218
Definition GarbageCollection.cpp:624
UE::GC::Private::FStats GetGarbageCollectionStats()
Definition GarbageCollection.cpp:6057
Definition GCObjectReferencer.cpp:27
int32 GetNumThreadsForGather(const EGatherOptions Options, const int32 NumObjects)
Definition ReachabilityAnalysisState.h:141
EGatherOptions
Definition ReachabilityAnalysisState.h:135
U16 Index
Definition radfft.cpp:71
static double Seconds()
Definition AndroidPlatformTime.h:20
Definition FastReferenceCollector.h:245
Definition FastReferenceCollector.h:334
Definition ReachabilityAnalysis.h:81
Definition ReachabilityAnalysisState.h:171
static int32 Num(const PayloadType &InPayload)
Definition ReachabilityAnalysisState.h:172
static void Append(const PayloadType &InSource, PayloadType &OutDest)
Definition ReachabilityAnalysisState.h:188
static bool Reserve(const TArray< TGatherIterator< PayloadType >, TInlineAllocator< 32 > > &ThreadIterators, PayloadType &OutPayload)
Definition ReachabilityAnalysisState.h:177
Definition ReachabilityAnalysisState.h:156
int32 StartIndex
Definition ReachabilityAnalysisState.h:158
int32 Index
Definition ReachabilityAnalysisState.h:160
int32 Num
Definition ReachabilityAnalysisState.h:162
PayloadType Payload
Definition ReachabilityAnalysisState.h:166
int32 LastIndex
Definition ReachabilityAnalysisState.h:164