profiler内存优化:警惕回调函数
最近做profiler内存优化,踩了一个深坑,觉得有必要做一下笔记。
过程是这样的,游戏启动后,会启动更新模块,加载更新界面,更新检测完成后会切换场景进入登陆界面。切换场景会自动释放上一个场景的资源。
但是问题来了,切换场景后,更新界面关闭了,但是更新界面引用的atlas、font之类的asset资源(这些资源仅使用在更新界面),没有自动释放,还存在内存中。
如下图的动态字库,占了18MB内存, Update就是atlas材质球引用的贴图,占了2MB内存。
反复的检查了代码,没有设置DontDestroyOnLoad,没有静态引用任何资源,更新窗体脚本的OnDestroy也是调用了的,百思不得解。
最后不得不用最笨的办法,一段一段代码注释掉,看是否哪块代码出了问题。首先从Awake开始,直接做切换场景,然后看profiler
Update贴图已经不在了,有戏。然后放开Awake,继续,最后终于查到一段代码
这里DownDllCallback最后回调函数传递给一个子线程,因为回调函数是一个成员函数,传递参数会把当前类的this指针给传进去,导致其他地方
对这个类有引用,切换场景自然就不能自动释放了。搞了半天,原来是回调函数惹的祸。
解决办法有两个:
1. 将回调函数设置成静态函数,这样就不带this指针了
2. 在适当的地方,将回调函数卸载掉,也就是事件注册和反注册,必须成对呀
总结:
1. 在MonoBehaviour脚本中,回调函数的使用也要注意,一不注意就导致脚本有多余引用,还不容易发现
2. 要保持良好的代码习惯,通常注册了函数,使用完后没有对函数进行反注册,这个要时刻警惕,出问题真不好查。