在游戏运行的时候,数据主要存储在内存中,当游戏的数据在不需要的时候,存储当前数据的内存就可以被回收以再次使用。内存垃圾是指当前废弃数据所占用的内存。 GC即(Gabarage Collector,垃圾回收器)是指将废弃的内存重新回收再次使用的过程。
代码分配的内存,是通过Mono虚拟机,分配在Mono堆内存上的,其内存占用量一般较小,主要目的是程序猿在处理程序逻辑时使用; 比如:通过System命名空间中的接口分配的内存,将会通过Mono Runtime分配在Mono堆。
而Unity的资源,是通过Unity的C++层,分配在Native堆内存上的那部分内存。 比如通过UnityEngine命名空间中的接口分配的内存,将会通过Unity分配在Native堆;
对于目前绝大多数基于Unity引擎开发的项目而言,其托管堆内存是由Mono分配和管理的。“托管” 的本意是Mono可以自动地改变堆的大小来适应你所需要的内存,并且适时地调用GC操作来释放已经不需要的内存, 但是GC并不是实时管理的,是需要通过程序员手动或系统定时触发的。因为GC是一个耗时的操作,可能在有些系统中触发的不合时宜(明显卡顿)。所以,GC也需要优化,需要控制在合事宜的情况触发。比如游戏中我们需要在切换Loading时触发GC,而在游戏战斗中控制不能被触发。 因此优化GC,就是优化堆内存,就是尽量减少堆内存,及时回收堆内存。
1. GC会不时地自动运行(频率因平台而异) 2. 堆分配时堆上的可用内存不足时触发GC。
这个算法在每个对象上维护着一个字段来统计多个对象正在使用自己。当引用计数为0的时候,对象就可以从内存中删除了。 但是引用计数设计存在着一个致命的问题,那就是处理不好循环引用。 比如:在一个界面里,父窗口持有了对子对象的引用,子对象又持有了父窗口的引用。这样的循环引用就会导致内存泄漏,即使不需要这2个对象了,也不会被删除。
根搜索就是从一个根开始遍历所有的叶子,然后把所有不需要的叶子清除。
贝姆垃圾回收(Boehm conservative collector):无分代\并行,执行时所有线程阻塞;每次标记都会访问所有可达的对象(穷举搜索垃圾)。这种方式极有可能在短时间造成帧率下降,影响玩家体验。
通过一个图的数据结构来收集对象的根,这个根就是引用地址。可以理解为指向托管堆的关系线。 当触发这个算法时,会检查图中的每个根是否可达,如果可达,则对其标记,然后在堆上找到剩余没有标记的对象进行删除,这样,那些不再使用的堆中对象就删除了。
Lua 5.0 采用的是一个折中的方案:每当内存分配总量超过上次 GC 后的两倍,就跑一遍新的 GC 流程。 但 Lua 5.0 这种会把整个虚拟机都停下来的 (Stop the World )的简单粗暴的 GC 实现 Lua 5.1 开始,Lua 实现了一个步进式垃圾收集器。 Lua 5.1 采用了一种三色标记的算法。每个对象都有三个状态:无法被访问到的对象是白色,可访问到,但没有递归扫描完全的对象是灰色,完全扫描过的对象是黑色。 随着收集器的运作,通过充分遍历灰色对象,就可以把它们转变为黑色对象,从而扩大黑色集。一旦所有灰色对象消失,收集过程也就完成了。 Lua 5.2 中 Lua 引入了分代 GC 。又在 Lua 5.3 中移除。 在还没有发布的 Lua 5.4 中,分代 GC 被重新设计实现。
装箱会产生垃圾源于底层,当一个值类型变量被装箱时,Unity在堆上创建一个临时的System.Object来包装值类型变量。一个System.Object是一个引用类型的变量,所以当这个临时对象被处理时会产生垃圾。
yield return 0;//会产生垃圾,int变量0被装箱。 =>>> yield return null yield return new WairforSeconds(1f);//如果多次被调用,会产生很多。 ==>>>WaitForSeconds delay =new WaitForSeconds(1f);//可以事先缓存起来 yield return delay;
您需要 登录 才可以下载或查看,没有账号?立即注册
使用道具 举报
本版积分规则 发表回复 回帖并转播 回帖后跳转到最后一页
小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )
GMT+8, 2025-3-15 01:59 , Processed in 0.858652 second(s), 27 queries .
Powered by Discuz! X3.5 Licensed
© 2001-2025 Discuz! Team.