前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >UnrealEngine4 源码剖析 (二) 垃圾回收

UnrealEngine4 源码剖析 (二) 垃圾回收

作者头像
Kindem
发布2022-08-12 14:12:16
9980
发布2022-08-12 14:12:16
举报
文章被收录于专栏:Kindem的博客

1. 垃圾回收

垃圾回收( GC )可以说是现代编程语言的标配,GC 简单来说就是语言运行时自动判别申请的内存是否还在被使用,判断内存无用后则自动回收内存。内存管理从来就不是什么容易事,需要手动管理内存实际上也是 C/C++ 入门门槛高的一大原因,稍有不慎就会造成内存泄露。

UnrealEngine4 在自己的 Runtime 中实现了 GC 功能,所有使用 NewObject()LoadObject() 方法创建的对象都会受 GC 系统的管制,当对象无用后将会自动释放。

2. UE4 GC 源码阅读

首先我们要知道,在 UE4 中,是不能通过 C++ 内置的操作符 new 来创建对象的,使用 new 创建的对象将不受 UE4 Runtime 的控制,正确的做法是使用 NewObject() 或者 LoadObject() 方法创建或加载对象。

首先我们需要知道,当使用 NewObject() 创建对象后,真正的内存将会被保存至一个全局数组中,另外还需要在一个全局 Hash 表中保存一些其他信息,这部分代码在 /Engine/Source/Runtime/CoreUObject/Private/UObject/UObjectHash.cpp,我们需要关注两个关键信息:

代码语言:javascript
复制
FUObjectArray GUObjectArray;

class FUObjectHashTables {
    // ...

    static FUObjectHashTables& Get()
	{
		static FUObjectHashTables Singleton;
		return Singleton;
	}
}

其中 GUObjectArray 就是全局对象数组,而 FUObjectHashTables 是一个单例,类内部维护了几张 Hash 表,存储了对象之间的关系。我们先看 GUObjectArray,它的类型是 FUObjectArray

FUObjectArray
FUObjectArray

FUObjectArray

可以看到内部封装了一个 FChunkedFixedUObjectArray,然后提供了一些 Index 与 对象之间转换的工具方法,我们再接着看 FChunkedFixedUObjectArray

FChunkedFixedUObjectArray
FChunkedFixedUObjectArray

FChunkedFixedUObjectArray

Objects 就是真正申请的内存了,通过 NewObject() 创建的对象都会保存在指针数组中。接下来我们看 FUObjectHashTables

FUObjectHashTables
FUObjectHashTables

FUObjectHashTables

不用多少,内部保存了很多张 Hash 表来存储对象之间的关系,然后提供了摇树压缩和 Hash 表相关操作的方法。

接下来,我们来看 GC 的整体流程,GC 的起点是 UWorld#Tick(),可以顺着我给的时序图来梳理整个流程:

GC
GC

GC

UWorld#Tick() 中会调用 UEngine#ConditionalCollectGarbage() 来开始垃圾收集,其中又会调用全局方法 CollectGarbage(),其中会先获取全局锁,暂停主线程以外的所有线程,即 GC 中常见的 “Stop The World” 操作,此时主线程会完全被 GC 工作占用,其他线程被锁停止。

开始 GC 后,会调用 FRealTimeGC#PerformReachabilityAnalysis() 方法来进行对象可达性分析,UE4 使用的 GC 算法是 “标记-清除” ,从后面调用的 MarkObjectsAsUnreachable()CollectReferences() 也能看出端倪。

在完成对象标记后,会调用 GatherUnreachableObjects() 方法来收集所有不可达的对象,并将其保存在一个临时数组中,之后会调用 UnhashUnreachableObjects() 方法来销毁所有不可达的对象,这一步中会调用到 UObject 的生命周期 BeginDestroy(),在基类的实现中有具体的销毁流程。

最后调用 ShrinkUObjectHashTables() 方法针对全局 Hash 表 FUObjectHashTables 进行摇树压缩,完成后释放 GC 锁,这样就完成了一轮 GC 的所有流程。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 垃圾回收
  • 2. UE4 GC 源码阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档