Unity内存泄露,高频GC需要注意的地方(持续更新中...)
---恢复内容开始---
Unity的mono虚拟机占用的是堆内存,应该也是使用了内存池之类的机制,释放掉对象,堆内存是不会被释放的。所以要管理好堆内存,免得堆内存暴涨首先就把手机撑爆了。
首当其冲的是内存泄露,无用的资源始终占据着内存,需要用的时候又初始化实例,导致内存无法释放,占用的内存持续升高。
其次,高频率的实例化对象又释放对象,会看到GC一直很高。高GC会占用大量的CPU资源,导致游戏卡顿。
我会整理记录遇到的一些容易被忽视的,或者隐藏较深的问题。
1.Debug.Log会在各种模式下运行,虽然不会真的打印出来。当前的解决方案是,多封装了一层,用宏来控制只调用空方法体。
2.另外一个普遍的协程的错误是使用了new 当yield同一个值多次,会造成高频gc,并且高CPU消耗。当前的解决方案是,循环体的话,先实例化一个waitforseconds对象,然后yield之。
此外,我们自己写了一个单例Timer类(使用OnUpdate进行realTime计时,单次计时,多次触发,用委托将callback接口暴露出来。模仿LUA里面的Timer类),用于实现定时刷新。
3.频繁触发的方法,里面的实例化也应该做缓存。(比如消息体里面的memorystream之类)
4.方法的引用,无论是匿名方法还是命名方法,在Unity里面都是引用类型,都将会导致堆内存的分配,将匿名方法转变为闭包(匿名方法使用了在创建的时刻的局部变量的地方),会显著的增加内存的使用和堆内存的分配。so,委托的匿名写法: callback += () =>{//body} 的写法,如果要重复调用的,会造成GC,如果用了局部变量,还要造成额外的堆内存分配和使用,耍酷的同时是要付出代价的。
5.这个梗其实比较常识了。不过还是顺带说一下。LINQ和正则表达式会有装箱和拆箱操作,因此要尽量避免使用。当前项目中是禁止使用LINQ和正则的。
//date to 2016-11-29