找回密码
 立即注册
查看: 528|回复: 0

Unity用户手册-垃圾回收

[复制链接]
发表于 2021-1-29 09:00 | 显示全部楼层 |阅读模式
Unity的垃圾回收

可以把GC想象成一个描述程序对象之间互相引用的算法。如果在程序中一个子对象被其父对象引用(在原生代码中使用的是指针),那他们的关系图如下:


当GC对一个进程的内存进行扫描,它会尝试寻找没有父亲的对象。如果找到,就对他们进行回收以便释放内存给其他需求使用。
当然,其实大部分的对象都有父对象,因此GC需要确切的知道哪些对象是重要的父对象,这些对象是你的程序中真正正在使用的。用GC的术语来说,这些对象叫做“根”。下面的例子展示了两种不同的情况:


在上面的图片中,Parent2没有根对象,因此GC可以释放Parent2和其孩子Child2的内存以便重新使用。但是Parent1和Child1的情况不同,Parent1有根对象,因此GC不能回收他们,因为他们还在被程序使用。


对于.NET来说,有三类根对象:
        在托管代码线程栈上的局部变量    静态变量    GCHandle 对象




在托管代码线程栈上的局部变量
当一个线程被注册到垃圾回收器中,GC会把这个线程栈中的所有对象当成“根”对象。让我们看下那个线程中生成出来的原生代码(在HelloWorld_AnotherThread_m4函数中):
AnyClass_t1 * L_0 = (AnyClass_t1 *)il2cpp_codegen_object_new (AnyClass_t1_il2cpp_TypeInfo_var);
AnyClass__ctor_m0(L_0, /*hidden argument*/NULL);
V_0 = L_0;
我们能看到一个局部变量: L_0。GC必须将其视为“根”对象。在这个线程的短暂的执行过程中,这个“AnyClass”对象和其所引用的其他对象所占用的内存空间不能被GC回收另作他用。绝大部分在栈上的变量对于GC来说都是“根”对象,因为这些变量所在的函数都是在一个线程中被执行的。


当线程退出的时候,il2cpp_gc_unregister_thread函数被调用,用来告知GC这些对象已经不是“根”对象了。因此GC可以通过回收L_0来释放AnyClass所占用的内存空间。


静态变量
有些变量不在线程调用栈上。这些静态变量也需要被当成“根”对象处理。


GCHandle对象
假设你不想使用静态变量,但是你又想当GC回收他们的时候对变量有更多一些的控制权。特别的,当你将托管代码中的一个对象传递给原生代码,而原生代码又要保持这个对象的时候,我们必须告诉GC这些对象是“根”对象,不能被回收。这个是通过一个特殊的GCHandle对象来实现的。


GCHandle的创建告诉运行时代码这些对象应当被当成“根”对象处理,此对象以及其引用到的对象都不能回收重用。


IL2CPP运行时是如何和GC交互的:
通过“根”对象的概念让GC知道哪些对象可以被回收,而哪些不行。


Unity的垃圾收集

垃圾收集器定期运行(注意:确切的时间与平台有关)。这将扫描堆上的所有对象,标记删除任何不再引用的对象。然后删除未引用的对象,释放内存。
至关重要的是,Unity的垃圾收集 - 使用Boehm GC算法 - 是Non-generational和非压缩的。“Non-generational”意味着GC在执行收集传递时必须扫描整个堆,因此其性能因堆扩展而降低。“非压缩”意味着内存中的对象不会重新定位,以便关闭对象之间的间隙。
上图显示了内存碎片的示例。释放对象时,将释放其内存。但是,释放的空间也不会成为“空闲内存”的一部分。释放对象两侧的对象可能仍在使用中。因此,释放的空间是存储器的其他部分之间的“间隙”(该间隙由图中的红色圆圈表示)。因此,新释放的空间仅可用于存储与释放的对象相同或更小的数据。
分配对象时,请记住该对象必须始终占用内存中的连续空间块。
这导致了内存碎片的核心问题:虽然堆中可用空间的总量可能很大,但是该空间中的一些或全部可能在分配的对象之间存在小的“间隙”。在这种情况下,即使可能有足够的总空间来容纳某个分配,托管堆也找不到足够大的连续内存块来适应分配。
但是,如果分配了大对象并且没有足够的连续可用空间来容纳对象,则如上所述,Unity内存管理器执行两个操作。
首先,如果还没有这样做,垃圾收集器就会运行。这会尝试释放足够的空间来完成分配请求。
如果在GC运行后,仍然没有足够的连续空间来满足请求的内存量,则堆必须扩展。堆扩展的具体数量取决于平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-15 19:57 , Processed in 0.089305 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表