首页 > 其他分享 >虚幻4引擎垃圾回收原理

虚幻4引擎垃圾回收原理

时间:2022-11-29 20:35:04浏览次数:37  
标签:UObject 函数 标记 对象 回收 引擎 引用 虚幻 垃圾


虚幻引擎的GC是追踪式、非实时、精确式,非渐近、增量回收(时间片)。

垃圾回收算法分类:

分类

项目

描述

引用计数/追踪式GC

引用计数

通过额外的计数来对单个对象的引用次数进行计算,当引用计数为零时,回收对象

 

追踪式

扫描系统对象引用网络,寻找被引用的对象,留下的对象即为需要回收的垃圾对象

保守/精确

保守式

不需要额外信息来进行辅助识别指针字段,根据一些特性推断出可能为指针的区域,根据这些指针判断对象已被引用,从而释放“绝对不可能被引用”的对象,不求全部回收,但求不错删

 

精确式

需要额外信息来进行辅助识别指针字段,但是能够精确识别每一个被引用的对象

实时/非实时

实时

实时GC不需要中断用户程序进行

 

非实时

非实时GC会要求中断用户程序运行来进行垃圾回收

渐进/非渐进

渐进

逐步完成搜索与回收

 

非渐进

一次完成搜索和回收操作

UClass包含了类的成员变量信息,类的成员变量包含了“是否是指向对象的指针”,因此具备选择精确式GC的客观条件。

利用反射系统,完成对每一个被引用的对象的定位。故采用追踪式GC。

虚幻在回收过程中,没有搬迁对象,应该是考虑到对象搬迁过程中修正指针的庞大成本。

选择了一个非实时但是渐进式的垃圾回收算法,将垃圾回收的过程分步、并行化,以削弱选择追踪式GC带来的暂停等消耗。

 

垃圾回收函数 CollectGarbage

  1. 锁定
  2. 回收
  3. 解锁

 

虚幻的GC入口是CollectGarbage()

COREUOBJECT_API void CollectGarbage(EObjectFlags KeepFlags, bool bPerformFullPurge = true);
void CollectGarbage(EObjectFlags KeepFlags, bool bPerformFullPurge)
{
// No other thread may be performing UOBject operations while we're running
GGarbageCollectionGuardCritical.GCLock();

// Perform actual garbage collection
CollectGarbageInternal(KeepFlags, bPerformFullPurge);

// Other threads are free to use UObjects
GGarbageCollectionGuardCritical.GCUnlock();
}

锁定/解锁

借助GGarbageCollectionGuardCritical.GCLock/GCUnLock函数,在垃圾回收期间,其他线程的任何UObject操作都不会工作,从而避免出现一边回收一边操作导致各种问题。

回收

回收过程对应函数CollectGarbageInternal中的FRealtimeGC::PerfomReachablilityAnanlysis函数,可以看做两个步骤:标记和清除。不过,增加了簇和增量清除,簇是为了提高回收效率,增量清除是为了避免垃圾回收时导致的卡顿。

 

标记过程:全部标记为不可达,然后遍历对象引用网络来标记可达对象。

清除过程:直接检查标记,对没有被标记可达的对象,调用ConditionalBeginDestroy函数来请求删除。

 

标记过程的实现原理:

全部标记为不可达:虚幻引擎的MarkObjectsAsUnreachable函数就是用来标记不可达的。借助FRawObjectIterator遍历所有的UObject,然后设置标记为Unreachable即可。

MarkObjectsAsUnreachable(ObjectsToSerialize, KeepFlags);

遍历对象引用网络来标记可达对象:

FGCReferenceProcessor ReferenceProcessor;
TFastReferenceCollector<FGCReferenceProcessor, FGCCollector, FGCArrayPool> ReferenceCollector(ReferenceProcessor, FGCArrayPool::Get());
ReferenceCollector.CollectReferences(ObjectsToSerialize, bForceSingleThreaded);

这里有几个重要的对象TFastReferenceCollector、FGCReferenceProcessor、以及FGCCollector,分别介绍一下。

 

TFastReferenceCollector:用于可达性分析。

如果是单线程就调用ProcessObjectArray()函数,遍历UObject的记号流(token stream)来查找存在的引用,如果没有记号流,调用UClass::AssembleReferenceTokenStream()函数就是用生成记号流(token steam,其实就是记录了什么地方有UObject引用),用CLASS_TokenStreamAssembled来保存。

如果是多线程,创建几个FCollectorTask来处理,最终还是调用ProcessObjectArray()函数来处理。

 

UClass::AssembleReferenceTokenStream()函数

如果没有创建token stream,那么就会遍历当前UClass的所有UProperty,对每个UProperty调用EmitReferenceInfo()函数,这是一个虚函数,如果它有父类,那么就会调用父类的AssembleReferenceTokenStream()函数,并把父类添加到数组的前面,最后加上GCRT_EndOfStream到记号流中,并设置CLASS_TokenStreamAssembled来保存。

 

FGCReferenceProcessor

处理由TFastReferenceCollector查找得到的UObject引用。

如果Object->IsPendingKill()的返回值为true且允许引用消除,那么把Object的引用设置为NULL

否则,调用ThisThreadAtomicallyClearedRFUnreachable()清除不可达标记,标记为可达,如果这个UObject是簇的根,调用MarkReferencedClustersAsReachable函数,把当前簇引用的其他簇标记为可达。

 

基于簇的垃圾回收

其中跟Cluster相关的几个函数在UObjectBaseUtility中,如下图所示:

虚幻4引擎垃圾回收原理_虚幻引擎垃圾回收

用于加速Cook后的对象的回收,所以编辑器下不会使用簇来GC。能够作为簇根的为UMaterial和UParticleSystem,基本上所有的类都可以在簇中。当垃圾回收阶段检查到一个簇根不可达,整个簇都会被回收,加速回收的效率,节省了再去处理簇的子对象的时间。

 

FGCCollector

继承自FReferenceCollector,HandleObjectReference()和HandleObjectReferences()都调用了FGCReferenceProcessor的HandleObjectReference()方法来进行UObject的可达性分析。

 

清除过程的实现原理:

为了减少卡顿,虚幻增加了增量清除的概念(IncrementalPurgeGarbage()函数),就是一次删除只占用固定的时间片,一段段进行销毁的触发。

  • 需要注意的是,由于会在两次清除时间内产生新的UObject,故在每次进入清除时,需要检查GObjCurrentPurgeObjectIndexNeedsReset,如果为true,那么重新创建一个FRawObjectIterator用于遍历所有的UObject。
  • 通过GObjCurrentPurgeObjectIndex来循环遍历所有的FUObjectItem(记录了UObject相关的信息,比如ClusterIndex,Flags等),如果对象不可达且IsReadyForFinishDestroy()为true,那么我们就调用ConditionalFinishDestroy();
  • 而如果IsReadyForFinishDestroy()为false,那么把它添加到GGCObjectPendingDestruction中去。待到下一次增量清除时,如果GGCObjectPendingDestructionCount不为0且IsReadyForFinishDestroy()为true,那么我们就调用ConditionalFinishDestroy()。
  • 当然如果有时间限制,到了时间限制,也会退出。


标签:UObject,函数,标记,对象,回收,引擎,引用,虚幻,垃圾
From: https://blog.51cto.com/u_6871414/5896982

相关文章

  • Python之垃圾回收机制
    什么是垃圾回收    当为一个变量分配数据的时候,python会在内存中分配一部分空间,用户储存此数据,但内存空间总是有限的,如果一直占用内存空间,内存迟早会溢出,所以,程序中需......
  • 什么是WebGL之基于WebGL的3D可视化引擎
    定义WebGL(WebGraphicsLibrary)是一个JavaScriptAPI,用于在任何兼容的Web浏览器中渲染高性能交互式3D和2D图形,而无需使用插件。WebGL通过引入一个非常符合OpenGLES2.0的......
  • 火山引擎 VeDI 推出这款产品 助力企业实现以“人”为中心的数据洞察
    更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群CDP(CustomerDataPlatform,客户数据平台)市场将迎来新一轮的高速增长。国际数据公司(以下......
  • 规则引擎Drools在贷后催收业务中的应用
    作者:vivo互联网服务器团队-FengXiang在日常业务开发工作中我们经常会遇到一些根据业务规则做决策的场景。为了让开发人员从大量的规则代码的开发维护中释放出来,把规......
  • 第2-4-8章 规则引擎Drools实战(1)-个人所得税计算器
    目录9.Drools实战9.1个人所得税计算器9.1.1名词解释9.1.2计算规则9.1.2.1新税制主要有哪些变化?9.1.2.2资较高人员本次个税较少,可能到年底扣税增加?9.1.2.3关于年度汇......
  • 视图引擎Smarty的简单使用
    参考: ​​http://www.jb51.net/article/5091.htm​​参考:​​http://baike.baidu.com/link?url=FFySw2r-dsE-lTdQgGy2DpLhciXM-JqUagEIydE_aFY3rGMnlYrf4eOOWw-fK-MFNFMp8v......
  • MySQL事务和存储引擎
    一、MySQL事务概述1.1、MySQL事务简介MySQL事务是访问并更新数据库中各种数据项的一个程序执行单元。在事务中的操作,要么都执行修改,要么都不执行,这就是事务的目的,也是事......
  • 护河神器-自动收集水面垃圾!
    随着城市的快速发展,城市内河产生了大量的生活垃圾和生活污水,导致水质持续恶化。随意丢弃的生活垃圾导致河流浊度增加,水中悬浮固体增加,导致水中鱼类和藻类的生态破坏。然而......
  • 图分析引擎技术方案调研
    图分析引擎-技术调研报告先上调研结论:金融领域相关图分析图查询引擎的建设,建议采用neo4j为内核进行研发图谱集群,可以部署到云平台自主运维或者选择服务厂商完全托管(建议自......
  • 企业级自定义表单引擎解决方案(十七)--Job配置执行
    .netcore研发的低代码自定义表单引擎,采用强大的规则引擎将所有的业务串联起来的,和其他低代码平台是有本质的区别的,目标是完全解放繁琐的CRUD工作。常规的业务,在需求以及......