UE4----GC(垃圾回收)

近日在UE4的反射,UE4的反射包含许多方面。这篇文章主要分析有效UE的垃圾回收机制(Garbage Collection)。这是一种动态的内存管理机制。当一个电脑上的动态内存不需要时,就应该予以释放,这种自动的资源管理,称为垃圾回收,这种动态的释放内存机制,可以减少工作当中或者项目当中所犯得错误。
在分析UE GC时我们要知道以下的知识
算法分类:

1.引用计数GC和追踪式GC
引用计数式GC通过额外的计数来实时计算对单个对象的引用次数,当引用次数为0时回收对象。引用计数的GC是实时的。像微软COM对象的加减引用以及C++中的智能指针都是通过引用计数来实现GC的。
追踪式GC算法在达到GC条件时(强制GC或者内存不够用,到达GC间隔时间)通过扫描系统中是否有对象的引用来判断对象是否存活,然后回收无用对象。
2.搬迁式和非搬迁式
搬迁式GC在GC的过程中需要移动对象在内存中的位置,当然移动对象位置后需要将所有引用到这个对象的地方更新到新位置(有的通过句柄来实现,而有的可能需要修改所有引用内存的指针)。
非搬迁式GC跟搬迁式GC正好相关,在GC 的过程中不需要移动对象的内存位置。
3.实时和非实时GC
实时GC是指不需要停止用户执行的GC方式。而非实时GC则需要停止用户程序的执行。
4.渐进式和非渐进式GC
和实时GC一样不需要中断用户程序运行,不同的地方在于渐进式GC不会在对象抛弃时立即回收占用的内存资源,而在GC达成一定条件时进行回收操作。
回收算法:
1.引用计数式
引用计数算法是即时的,渐进的,对于交互式和实时系统比较友好,因为它几乎不会对用户程序造成明显的停顿
优点:
·引用计数方法是渐进式,它能及时的释放无用的对象,将内存管理的开销实时的分布在用户程序运行过程中。
缺点:
·引用计数方法要求修改一个对象的引用时必须调整旧对象的引用计数和新对象的引用计数,这些操作增加了指针复制的成本,在总体开销上而言通常比追踪式GC要大。
·引用计数要求的额外的空间来保存计数值,这通常要求框架和编译器支持。
·实际应用中很多对象的生命周期很短,频繁的分配和释放将导致内存碎片化严重,内存碎片意味着可用内存在总数量上足够但是由于不连续而实际上不可用,同时增加内存分配的时间。
·引用计数算法最严重的问题就是环形引用问题(可以通过弱指针解决)
2.追踪式GC
追踪式GC算法通过递归的检查对象的可达性来判断对象是否存活,进而回收无用内存。
追踪式的GC算法的关键在于准确并快速的找到所有可达对象,不可达的对象对于用户程序来说是不可见的,因此清扫阶段通常可以和用户 程序并行执行。
3.标记清扫(Mark-Sweep)
标记清扫式GC算法是后面介绍的追踪式GC算法的基础,他通过搜索整个系统中对对象的引用来检查对象的可达性,以确定对象是否需要回收。
分类:追踪式,非实时,保守(非搬迁式)或者精确式(搬迁式),非渐进。
优点:
·相对于引用计数算法,完全不必考虑环形引用问题。
·操纵指针时没有额外的开销。
·与用户程序完全分离
缺点:
·标记清扫算法是非实时的,它要求在垃圾收集器运行时暂停用户程序运行,这对于实时和交互式系统的影响非常大。
·基本的标记清除算法通常在回收内存时会同时合并相邻空闲内存块,然而在系统运行一段时间后仍然难免会生成大量的内存碎片,内存碎片意味着可用内存的总数量上足够,但实际上不可用,同时还会增加分配内存的时间,降低内存访问的效率。
·保守式的标记清除算法可能会将某些无用对象当做存活对象,导致内存泄漏。
用户程序化时向系统预申请一块内存,新的对象申请在此取余内分配,用户程序不需要主动释放已分配的空间,当达到回收条件,或者用户程序主动请求时开始收集内存。标记清扫式算法分为两个阶段:标记阶段和清扫阶段。
标记阶段:
从根结点集合开始递归的标记所有可达对象。
根节点结合通常包括所有的全局变量,静态变量以及栈区。这些数据可以被用户程序直接或者间接引用到。
清扫阶段:
遍历所有对象,将没有标记为可达的对象回收,并清理标记位。
保守式标记清扫算法:
保守式的标记清扫算法缺少对象引用的内存信息,它假定所有的根节点集合为指针,递归的将这些指针指向的内存堆区标记为可达,并将所有可达区域的内存数据假定为指针,重复上一步,最终识别出不可达的内存区域,并将这些区域回收。
保守式的GC算法可能会导致内存泄漏。由于保守式GC算法没有必须的GC信息,因此必须假设所有内存数据是一个指针,这很可能将一个非指针数据当作指针,比如将一个整形值当作一个指针,并且这个值碰巧在已经分配的堆区域地址范围内,这将会导致这部分内存被标记为可达,进而不能被回收。
保守式的GC不能确定一个内存上的数据是否是一个指针,因此不能移动对象的位置。
实际应用:
保守式标记清扫GC算法:Boehm-Demers-Weiser算法
标记缩并:
有些情况下的内存管理的性能瓶颈在分配阶段,内存碎片增加了查找可用内存区域的开销,标记缩并算法就是为了处理内存碎片问题而产生的。
分类:追踪式,非实时,精确式,搬迁式,非渐进
节点复制:
节点复制GC通过将所有存活对象从一个区移动到另一个区来过滤非存活对象。
分类:追踪式,非实时,精确式,搬迁式,非渐进
分代式GC(Generational Garbage Collection)
在程序运行过程中,许多对象的生命周期是短暂的,分配不久即被抛弃。因此将内存回收的工作焦点集中在这些最有可能是垃圾的对象上,可以提高内存回收的效率,降低回收过程的开销,进而减少对用户程序的中断。
分代式GC每次回收时通过扫描整个堆中的一部分而不是全部来降低内存回收过程的开销。
分类:追踪式,非实时,精确式,搬迁式,非渐进
渐进式GC
渐进式GC要解决的问题是如何缩短自动内存管理引起的中断,以降低对实时系统的影响。
渐进式GC算法基于分代式GC算法,它的核心在于用户程序运行过程中维护年轻分代的根节点集合。
具体分析UE中的GC我们将在下一篇文章中指出。

本文参考:
https://www.cnblogs.com/ghl_carmack/p/6112118.html
http://www.cnblogs.com/superjt/p/5946059.html

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值