Garbage Collection分类
- UE4采用”追踪式、精确式、非搬迁式、非实时、非渐进式”的标记清扫GC算法。分为两个阶段:标记阶段(GC Mark)和清扫阶段(GC Sweep)
- 追踪式:达到GC条件时(内存不够用、到达GC间隔时间或者强制GC)通过扫描系统中是否有对象的引用来判断对象是否存活,然后回收无用对象
- 精确式:在回收过程中能准确得识别和回收每一个无用对象的GC方式,为了准确识别每一个对象的引用,通过需要一些额外的数据(比如虚幻中的属性UPROPERTY)
- 非搬迁式:在GC过程中不需要移动对象的内存位置
- 非实时:需要停止用户程序的执行
- 非渐进式:在对象抛弃时立即回收占用的资源
- 被UPROPERTY宏修饰或AddReferencedObject函数被手动添加引用的UObject成员变量,才能被GC识别追踪,GC通过这个机制建立起引用链(Reference Chain)网络
- 当UObject对象没有直接或间接被根节点Root对象引用或设置为PendingKill状态,就被GC标记为垃圾,并被GC回收
- 注意:USTRUCT宏修饰的结构体、FGCObject对象不被GC管理
基础概念及操作
- 置nullptr:若将UObject对象的UPROPERTY宏修饰的UObject成员变量置为nullptr,只会断掉这个节点的子链路
- 获取UObject对象对应的FUObjectItem:GUObjectArray.IndexToObject(Obj->GetUniqueID( ))
- AddToRoot函数会将UObject对象加到根节点Root上,让其不被GC回收;RemoveFromRoot函数会将UObject对象从根节点移除,可被GC回收
- 标记为PendingKill
- UObject对象不为Root对象,调用MarkPendingKill设置为等待回收对象
- 通过IsPendingKill函数来判断一个UObject是否处于PendingKill状态
- 调用ClearPendingKill函数来清除PendingKill状态
防止被GC的方法
- AddToRoot函数将UObject对象加到根节点Root上
- 直接或间接被根节点Root对象引用
- 直接或间接被存活的FGCObject对象引用
- 注意:以上方法只是防止,可以通过相应的操作让其被GC回收
标记阶段(GC Mark)
- 从根节点集合开始,标记处所有不可达对象。该阶段执行时需要保证对象引用链不被修改,因此是阻塞的
清扫阶段(GC Sweep)
- 阶段遍历所有对象,将标记为不可达的对象回收。该阶段可通过限制时间来分帧异步执行,避免导致卡顿
判断UObject对象有效性
- Isvaild全局函数:判断UObject对象指针是否为空以及是否为PendingKill状态