bTrackHistory
bTrackHistory
#Overview
name: bTrackHistory
The value of this variable can be defined or overridden in .ini config files. 1
.ini config file referencing this setting variable.
It is referenced in 8
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of bTrackHistory
is to control whether the garbage collection system should track and record the history of object references during the reachability analysis phase. This setting variable is primarily used in the garbage collection and object reference tracking systems of Unreal Engine 5.
Based on the callsites provided, the bTrackHistory
variable is used within the CoreUObject module, specifically in the garbage collection subsystem. It’s primarily referenced in the GarbageCollection.cpp
file, which is responsible for managing memory and cleaning up unused objects.
The value of this variable is typically set based on whether the FGCHistory system is active. This can be seen in the constructor of the TDebugReachabilityProcessor
class:
bTrackHistory(FGCHistory::Get().IsActive())
The bTrackHistory
variable interacts with several other variables and systems:
- It’s often used in conjunction with
bTrackGarbage
, which controls garbage reference tracking. - It’s used alongside the
MarkStack
in Verse (Epic’s custom scripting language) related garbage collection. - It influences the behavior of the
IsTimeLimitExceeded()
function when incremental reachability analysis is active.
Developers should be aware of the following when using this variable:
- Enabling history tracking can have performance implications, as it requires additional memory and processing to store reference information.
- It’s particularly important when debugging memory issues or when detailed object reference information is needed.
- The variable is used in conditional statements to determine whether to record additional reference information, so its state can significantly affect the behavior of the garbage collection system.
Best practices when using this variable include:
- Only enable history tracking when necessary, such as during debugging sessions or when investigating memory issues.
- Be aware of the performance impact when enabling this feature, especially in performance-critical scenarios.
- Use in conjunction with other debugging tools and variables (like
bTrackGarbage
) for a comprehensive view of object references and memory management. - When implementing custom garbage collection or reference tracking systems, consider following the pattern established in the engine code, checking this variable before performing history-related operations.
#Setting Variables
#References In INI files
Location: <Workspace>/Engine/Config/BaseEngine.ini:3236, section: [AutomationController.History]
- INI Section:
AutomationController.History
- Raw value:
false
- Is Array:
False
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Source/Runtime/CoreUObject/Private/UObject/GarbageCollection.cpp:3309
Scope (from outer to inner):
file
function TVerseDebugReachabilityVisitor
Source code excerpt:
, PermanentPool(InPermanentPool)
, MarkStack(InMarkStack)
, bTrackHistory(bInTrackHistory)
{
}
virtual void VisitNonNull(Verse::VCell*& InCell, const TCHAR* ElementName) override
{
Context.Stats.AddVerseCells(1);
if (MarkStack.TryMarkNonNull(InCell) && bTrackHistory)
{
Verse::FAbstractVisitor::FReferrerContext* VisitorContext = GetContext();
if (VisitorContext != nullptr && VisitorContext->GetReferrer().IsCell())
{
const Verse::VCell* Referencer = VisitorContext->GetReferrer().AsCell();
GetContextHistoryReferences(Context, FReferenceToken(Referencer), 0).Add(FGCDirectReference(InCell, FName(ElementName)));
#Loc: <Workspace>/Engine/Source/Runtime/CoreUObject/Private/UObject/GarbageCollection.cpp:3336
Scope (from outer to inner):
file
function virtual void VisitNonNull
Source code excerpt:
FReferenceMetadata Metadata(GUObjectArray.ObjectToIndex(InObject));
bool bReachedFirst = TReachabilityProcessor<Options>::HandleValidReference(Context, FImmutableReference{ InObject }, Metadata);
if (bReachedFirst && bTrackHistory)
{
if (Referencer != nullptr)
{
GetContextHistoryReferences(Context, FReferenceToken(Referencer), 0).Add(FGCDirectReference(InObject, FName(ElementName)));
}
}
#Loc: <Workspace>/Engine/Source/Runtime/CoreUObject/Private/UObject/GarbageCollection.cpp:3350
Scope: file
Source code excerpt:
const FPermanentObjectPoolExtents& PermanentPool;
Verse::FMarkStack& MarkStack;
bool bTrackHistory;
};
#endif
//////////////////////////////////////////////////////////////////////////
template <EGCOptions Options>
#Loc: <Workspace>/Engine/Source/Runtime/CoreUObject/Private/UObject/GarbageCollection.cpp:3462
Scope (from outer to inner):
file
class class TDebugReachabilityProcessor
function bool IsTimeLimitExceeded
Source code excerpt:
FORCEINLINE bool IsTimeLimitExceeded() const
{
if (IsWithIncrementalReachabilityAnalysis() && bTrackHistory && !bTrackGarbage)
{
return GReachabilityState.IsTimeLimitExceeded();
}
return false;
}
#Loc: <Workspace>/Engine/Source/Runtime/CoreUObject/Private/UObject/GarbageCollection.cpp:3475
Scope (from outer to inner):
file
class class TDebugReachabilityProcessor
function TDebugReachabilityProcessor
Source code excerpt:
TDebugReachabilityProcessor()
: bTrackGarbage(GGarbageReferenceTrackingEnabled != 0)
, bTrackHistory(FGCHistory::Get().IsActive())
, bForceEnable(GForceEnableDebugGCProcessor != 0)
{}
bool TracksHistory() const { return bTrackHistory; }
bool TracksGarbage() const { return bTrackGarbage; }
bool IsForceEnabled() const { return bForceEnable; }
FORCENOINLINE void HandleTokenStreamObjectReference(FWorkerContext& Context, const UObject* ReferencingObject, UObject*& Object, FMemberId MemberId, EOrigin Origin, bool bAllowReferenceElimination)
{
UE::GC::GDetailedStats.IncreaseObjectRefStats(Object);
#Loc: <Workspace>/Engine/Source/Runtime/CoreUObject/Private/UObject/GarbageCollection.cpp:3507
Scope (from outer to inner):
file
class class TDebugReachabilityProcessor
function FORCENOINLINE void HandleTokenStreamObjectReference
Source code excerpt:
bool bReachedFirst = TReachabilityProcessor<Options>::HandleValidReference(Context, FImmutableReference{Object}, Metadata);
if (bReachedFirst && bTrackHistory)
{
HandleHistoryReference(Context, ReferencingObject, Object, MemberId);
}
}
}
#Loc: <Workspace>/Engine/Source/Runtime/CoreUObject/Private/UObject/GarbageCollection.cpp:3519
Scope (from outer to inner):
file
class class TDebugReachabilityProcessor
function void HandleTokenStreamVerseCellReference
Source code excerpt:
if (GIsFrankenGCCollecting)
{
if (bTrackHistory)
{
HandleHistoryReference(Context, ReferencingObject, Cell, MemberId);
}
Verse::FMarkStack MarkStack;
MarkStack.Mark(Cell);
if (MarkStack.Num() > 0)
#Loc: <Workspace>/Engine/Source/Runtime/CoreUObject/Private/UObject/GarbageCollection.cpp:3542
Scope (from outer to inner):
file
class class TDebugReachabilityProcessor
Source code excerpt:
const FPermanentObjectPoolExtents PermanentPool;
const bool bTrackGarbage;
const bool bTrackHistory;
const bool bForceEnable;
FORCENOINLINE static void HandleGarbageReference(FWorkerContext& Context, const UObject* ReferencingObject, UObject*& Object, FMemberId MemberId)
{
const UObject* Referencer = ReferencingObject ? ReferencingObject : Context.GetReferencingObject();
if (IsValid(Referencer))