游戏开发Unity Mono内存管理:GC机制

参考:

        【Unity游戏开发】垃圾回收基础学习

总结:

Unity游戏运行时内存占用分以下几部分:

  • Mono堆:C# 代码
  • Native堆:资源,unity引擎逻辑,第三方逻辑。
  • 库代码:Unity库,第三方库。

Mono堆:

代码分配的内存,是通过Mono虚拟机,分配在Mono堆内存上的,其内存占用量一般较小,主要目的是程序猿在处理程序逻辑时使用;

通过System命名空间中的接口分配的内存,将会通过Mono Runtime分配在Mono堆

Mono内存分为两部分,

  • 已用内存(used):已用内存指的是mono实际需要使用的内存
  • 堆内存(heap):堆内存指的是mono向操作系统申请的内存
  • 两者的差值就是mono的空闲内存

Mono中的GC主要有以下几个步骤:

  1. 停止所有需要mono内存分配的线程。
  2. 遍历所有已用内存,找到那些不再需要使用的内存,并进行标记。
  3. 释放被标记的内存到空闲内存。
  4. 重新开始被停止的线程。
  5. GC释放的内存只会留给mono使用,并不会交还给操作系统,因此mono堆内存是只增不减的。

Mono内存泄漏分析

典型泄漏:

代码侧的泄漏,由于“存在该释放却没有释放的错误引用”,导致回收机制认为目标对象不是“垃圾”,以至于不能被回收

手动内存管理的泄漏,资源卸载是主动触发的,在触发了资源卸载之后,才清除对资源引用,但是有人忘记主动卸载。

但是,现在需要扩大定义:把对象已经不再需要使用却没有被GC回收的情况称为mono内存泄漏

面临的问题

  • 托管堆在GC后内存仍不足时,会继续申请新的内存,但GC所释放的内存会留给Mono使用并不会还给操作系统,这会导致游戏内存占用越来越高
  • GC时会暂停那些需要Mono内存分配的线程,无论是否在主线程调用都会造成一定程度的卡顿。
  • GC过程会进行遍历标记的耗时操作,虽然优化了内存,但无疑大大加重了CPU的负担。

猜你喜欢

转载自blog.csdn.net/qq1090504117/article/details/111775029