内存优化
1.场景策略选择-自动释放资源
勾选此项后,在场景切换的时候,会自动将旧场景中的使用资源自动释放掉。从而会减少内存占用。这里要注意其自动释放的并不包括场景中动态添加的对象。
2.管理动态加载的资源
- 动态加载接口
cc.loader.load
cc.loader.loadRes
cc.loader.loadResArray
cc.loader.loadResDir
这些接口都是异步的,只有在加载完成后才能够使用。不然无法使用。
- 自动释放资源
cc.loader.setAutoRelease
cc.loader.setAutoReleaseRecursively
- 使用方法
cc.loader.setAutoRelease(预制体节点,true);
当场景切换时,由于资源已经释放,脚本中如果保留了引用,此时该引用将会变为非法引用。可以使用setAutoRelease和setAutoReleaseRecursively来保留这些资源。
setAutoReleaseRecursively指定资源及资源递归引用到的所有资源
- 手动释放API
cc.loader.release
cc.loader.releaseRes
cc.loader.releaseAsset
cc.loader.releaseAll
但是如果直接使用cc.loader.release(预制体节点),释放一个预制体是不够的,因为资源是依赖一些图片资源的,此时只能去释放它所使用的配置文件。所以一般要搜索他所有的依赖资源然后释放才能完成正确的释放。
使用 cc.loader.release(cc.loader.getDependsRecursively(预制体节点) )方可完成。
使用Chrome中的Allocation Profile工具查看内存变化。
查找内存“垃圾”过程中需要注意的是:
注意简单的对象创建,例如数组,{}
注意不要忽略匿名函数
注意匿名函数使用的外部变量将被匿名函数持有
利用Timeline 观察 GC 调用频率
寻找长期不释放的蓝色内存
尽力使用可以重复使用的资源
- 比如子弹,怪物等对象我们可以使用对象池进行创建管理
- 尽量少使用cc.vec , cc.color , cc.size , {} ,[] 等这些类似的对象,尽量复用,减少来回创建的开销。
了解CPU的性能以及优化
使用Chrome中的Performance定位cpu使用情况
总之需要注意的是:
1、观察整体性能曲线图
2、观察分析局部显红热点帧
3、通过调用栈分析热点调用的函数
大多的情况下,都是由于自己没有合理的书写代码造成的,如内存泄漏,闭包处理,逻辑处理过于集中等情况导致的会出现热点帧的现象。此时我们可以利用一些插件来强制要求自己写好代码。如:ESLint,JSLint,TSLint工具。
JS代码级优化
很多时候我们对于CPU的优化都会从算法的方面着手,关于算法这一块优化方案多种多样,很多都需要根据项目的实际情况以及游戏的设计出发的。
我们经常会聚焦于算法级的优化上,而忽略掉代码级的优化。
这里带来的就是代码级的优化
1、数组操作
增加数组元素时,更推荐使用:
array[array.length] = 0;
相比较push的方法,代码执行效率上我们可以看下对比:
在这里插入图片描述
会有一定的提升,但提升的空间有限,因此不是强烈推荐,只是针对需要反复大量执行的代码时,更推荐使用。比如大量的a星寻路计算时,可以在编码时随手注意一下
2、for循环
常用的for循环我们有几种方式
for(let i = 0;i < arr.length; i++)
for (const key in arr)
for (const key of arr)
arr.forEach(element => {})
除了for-in这种方式外,其他三种for循环方式没有什么太大的差距
在这里插入图片描述
强烈不推荐使用for-in的方式进行for循环,效率极其低下,同时随着游戏不断的运行,for-in还不能被jit优化。因此千万不要使用for-in
3、arguments
js中如果要实现类似C++中的多态,可以通过arguments去达到。
这样我们可以通过相同的接口,只是参数的不一致从而达到不同的逻辑运行效果
function argumentsTest () {
if (arguments.length === 1) {
//......
}
else if (arguments.length === 2) {
//......
}
}
类似上面这样的使用。
这种方式虽然使用上看起来很秀,但要注意的是,性能也是极其低下的,需要这种情况,不要偷懒,多写几行代码,拆分成几个不同的函数进行调用会更好。
强烈推荐不要在工程中使用arguments
4、try-catch or try-finally 以及 eval
强烈建议不要使用任何的try-catch or try-finally 以及 eval,执行效率极其低下,很容易造成游戏的卡顿。
例如try-catch or try-finally系列,如果没有错误抛出,那就还好。一旦有错误抛出,效率直线下降。
5、global value
在使用全局变量时,类似下面这样
gIndex = 0;
for (let i = 0; i < n; i++) {
gIndex += i;
}
执行结果:在这里插入图片描述
不要直接使用gIndex,使用局部变量进行一下转换,效率会快很多:
var localIndex = gIndex;
localIndex = 0;
for (let i = 0; i < n; i++) {
localIndex += i;
}
执行结果:在这里插入图片描述
以上就是一些代码级优化上需要注意的地方,可以看到,如果时一些热点函数,需要大量重复执行的话,如果使用这些优化方案,通常会带来很大的提升。这也是从另一个角度去进行CPU性能的优化
最后感谢@BigBear023 的博客