前言
像 C 语言这样的底层语言一般都有底层的内存管理接口,比如
malloc()
和free()
。相反,JavaScript 是在创建变量(对象,字符串等)时自动进行了分配内存,并且在不使用它们时“自动”释放。释放的过程称为垃圾回收。这个“自动”是混乱的根源,并让 JavaScript(和其他高级语言)开发者错误的感觉他们可以不关心内存管理。
上面这句话源自MDN网的"内存",我们前端程序员在编写前端代码时候,往往会忽略代码占用的内存问题,因为我们很少遇到内存占用过多而导致浏览器内存崩溃的状况。(刚好不巧,我就遇到了)
业务
我这边的场景是这样的,使用three.js展示每个不同病人的人体器官,如下所示:
这代表着每次我跳转到浏览病人的器官页面,就会重建一次场景和重新向后端获取模型数据,业务方面我觉得一切正常,但使用软件久了之后就感觉很是卡顿,然后我调出内存选项卡一看,好家伙!!!
我跟大家解释一下这个图表达的是什么意思,大家先看看快照,快照1是我在第一次进入一个病人的器官展示页面时候的内存,快照2是我第二次进入病人的器官展示页面的内存,可以看到,两次内存整整提高了200多m!!!!
看过我以前发的文章就会知道只需要加入下面的代码就可以了:
//将每个模型释放
group.traverse(function (v) {
if (v.type === 'Mesh') {
v.geometry.dispose()
v.material.dispose()
}
v = null
})
// memoryManager.dispose()
scene.remove(group)
renderer.forceContextLoss()
renderer.dispose()
renderer.domElement = null
renderer = null
scene.clear()
scene = null
camera = null
THREE.Cache.clear();
但是,在此之前我们要怎么发现我们做出来的项目发生了内存泄漏呢?
解决方案
首先我们先看看调试工具的性能选项卡
点击1之后开启录制状态,工具栏就会变成如下状态:
然后可以点击停止,关闭录制状态,就可以看到工具栏变成如下:
而返回到我的项目这里,他是这样的:
可以很明显的看到js堆在退出three页面之后,基本完全没被回收,也由此可以看出页面内存泄漏。
我们也要注意一点,就是工具栏的一个垃圾桶图标
这个是手动触发垃圾回收,浏览器从2012年开始,垃圾回收算法从引用计数法转为标记清除法,我们是不能够使用js代码来出发浏览器垃圾回收的,它只会每过一段时间进行回收,当然如果你按了这个垃圾桶图标,他也会进行回收。
当我们使用性能选项卡开启录制性能或者关闭录制时候,最后都点击一下垃圾桶图标,因为浏览器可能还没来得及回收页面产生的垃圾,有可能造成我们误判内存泄漏。