UE5 增量垃圾回收深度解析
UE5 的垃圾回收(GC)采用 标记-清除(Mark & Sweep) 策略,通过遍历对象引用关系确定可达对象并清理其余内存。本文聚焦 UE5.6 的 增量垃圾回收,尤其是 增量标记(Incremental Marking) 的最新变化,以及 工程上实现该算法的优化。阅读前如已熟悉通用 GC 原理(例如 Lua 的三色标记),会更易理解 UE 的实现细节与优化策略。
从 STW 到 增量扫描
在 UE5.4 之前,GC 的可达性分析通常以 一次性完成(Stop-the-World) 的方式进行:扫描阶段暂停游戏逻辑,实现简单,但缺点是 停顿时间可能较长,带来 Gameplay 卡顿。
从 UE5.4 起,引擎引入 增量扫描:将可达性分析拆分到多帧执行,平滑每帧的 GC 开销。这引出了一个核心问题:
扫描间隙产生的新对象/新引用如何处理?
对象分配
对象通过 NewObject 分配时,会进入 UObjectBase 构造并注册到全局对象表 GUObjectArray:
1 | UObjectBase::UObjectBase(UClass* InClass, |
AddObject 会把对象注册到 GUObjectArray 并设置内部标志位:
1 | void UObjectBase::AddObject(FName InName, EInternalObjectFlags InSetInternalFlags, int32 InInternalIndex, int32 InSerialNumber, FRemoteObjectId InRemoteId) |
在 AllocateUObjectIndex 中,可见关键点:非 “DisregardForGC” 窗口下,新对象会被标上 “Reachable” 位,即默认可达:
1 | void FUObjectArray::AllocateUObjectIndex(UObjectBase* Object, EInternalObjectFlags InitialFlags, int32 AlreadyAllocatedIndex, int32 SerialNumber, FRemoteObjectId RemoteId) |
