关于javascript:页面崩溃原因分析及解决

83次阅读

共计 2650 个字符,预计需要花费 7 分钟才能阅读完成。

引言

在开发综合治理平台态势概览的大屏页面的过程,遇到了页面解体的问题,本帖子记录了解体的起因剖析和解决方案。

问题

关上综合治理平台,进入态势概览页面,停留在此页面一段时间,会呈现如下图所示的页面解体的状况。

起因剖析

注:以下操作环境倡议在浏览器隐身模式下进行,避免其余因素烦扰

应用工具

依据页面解体的提醒,能够初步断定是页面内存溢出导致的解体,为了验证内存是否溢出,能够应用 Chrome 浏览器自带的工具剖析验证。这里介绍三种工具的应用,能够结合实际需要来应用。

  1. 工作管理器

1) 打开方式:

2) 界面:

3)应用形式:
工作管理器的应用办法最为简略,关上须要剖析的页面,间接察看内存占用空间与 JavaScript 应用的内存即可。如果这两个数据持续上升,阐明内存正在透露。

  1. 开发者工具 Performance 面板

1)打开方式:
按 F12 关上开发者工具,抉择 Performance 栏
2)界面:

3)应用形式:
关上须要剖析的页面,等页面稳定下来后,点击 Performance 左上角的录制按钮开始录制,它会保留下页面的快照、JS Heap、Document、Nodes、Listener、GPU Memory 等信息。录制一段时间(最好在一分钟以上)后,进行录制,期待工具生成报告。

  1. 开发者工具 Memory 面板

1)打开方式:
按 F12 关上开发者工具,抉择 Memory 栏
2)界面:

3)应用形式:
这个工具的应用形式最为简单,这里只简略介绍下 Heap snapshot 的应用,感兴趣的能够自行搜寻其余应用形式。
首先,关上须要剖析内存的页面,点击工具左上方的录制按钮,生成剖析报告。
其次,进行一些可能导致内存回升的操作后,再次点击录制按钮,生成剖析报告。
最初,咱们有了两份剖析报告,通过菜单栏的下拉框抉择 Comparison 过滤剖析后果。察看 #New、#Deleted、#Delta 这三列,别离代表新增对象数、删除对象数、新增数与删除数的差值,找到那些只有新增,没有删除的对象,看看是被谁援用了,据此来找到可能导致内存溢出的代码。

确定内存溢出起因

关上态势概览页面后,通过工作管理器察看页面应用的内存,发现内存是持续上升的,这时再通过 Performance 工具进一步剖析。
以下是 Performance 的剖析后果:

通过剖析后果能够看到,内存资源在持续上升,再进一步察看后果,能够发现内存回升是存在一个阶梯式的回升周期的,为什么会产生这种景象呢?放大内存回升的局部进一步剖析看看:

上图显示了内存回升局部细节,把鼠标挪动到页面快照上,能够分明地看到,当上一个大屏页面轮播到下一个页面时,内存就会回升并且不会再降落到之前的程度。当初曾经有理由狐疑是页面轮播引起的内存溢出,所以,通过暂停页面轮播,再进行一次 Performance 剖析,看看剖析后果:


通过上图能够看到,暂停页面轮播后,并没有显著的回升趋势,阐明浏览器能够失常回收内存,并没有溢出。至此,曾经能够确定当页面轮播时内存会溢出。

剖析内存溢出对象

通过第二步的剖析,曾经晓得了大屏页面切换会导致内存升高,利用这个证据,用 Memory 工具去进一步剖析,找到那些被援用本该被开释,但理论没有的开释的对象
首先,关上态势概览页面,先暂停页面轮播切换,停留在总体态势页面,待页面加载实现,而后关上 Memory 工具,点击录制按钮剖析总体态势页面的内存。剖析实现后,手动切换到危险态势页面或者其余大屏页面,再切换回总体态势页面,而后在 Memory 工具中再次点击录制按钮剖析页面切换之后的内存。实现以上操作之后,就失去了两份剖析报告,别离是内存回升前和回升后的,在 Memory 工具的菜单栏下拉框中抉择 Comparison,看看到底是哪些家伙占用了内存!

来剖析下面的后果图,首先,页面上有各种类型的对象,点击对象能够看到对象具体的援用信息,咱们的工作是通过对象援用信息找到一些蛛丝马迹。咱们能够搜寻 detached 结尾归类的对象,也就是那些在内存中然而没有在页面进行渲染的元素。抉择一个,能够看到它的具体援用信息:

很显著,ehcarts 援用了这个对象,而这个对象连同它的援用,理当是在页面切换之后被销毁了的,既然他没有销毁,阐明咱们的代码是有问题的。接下来要做的是,找出 ehcarts 援用的对象没有被销毁的起因,批改相干代码,再验证。

解决方案

应用正确的 echarts 实例销毁办法

依据下面的起因剖析,咱们晓得是 echarts 援用的对象没有失常被销毁,那么很简略,咱们只有尝试正确销毁 echarts 实例就好了。进入到咱们的 ehcarts 组件代码,定位到 beforDestory 钩子,能够看到,曾经有一段代码对 echarts 实例进行开释了。

进入 echarts 官网查问销毁实例的相干 api,发现 .clear() 办法只是清空了实例,并没有销毁,而 .dispose() 办法才会销毁实例。

答案到这里曾经跃然纸上了,咱们我的项目中之前始终用的是 .clear() 办法清空 echarts 实例对象,而不是用 .dispose() 销毁,所以 echarts 实例并没有被失常销毁,当咱们频繁地切换页面的时候,echarts 实例就会一直的累加,占用的内存也会随之减少。所以,这里倡议,当前咱们封装 echarts 组件的时候,对立应用 .dispose() 办法销毁组件。

页面暗藏时进行定时器工作

你认为到这里就完结了吗?事件没有那么简略!在搜寻内存溢出解决方案的时候,在网上看到了一篇文章:https://www.cnblogs.com/zdd20…

再次通过 Performance 工具剖析验证,后果如下:

果然,内存又在继续减少,那么就应用网上分享的办法解决这个问题,增加一个标签切换的监听函数,在来到页面时,把页面的定时器革除,回来页面时从新开启定时器,这样就能够了。

后果

  1. 放弃在态势概览页面,并开启轮播页面,应用 Permermance 工具进行内存剖析

后果:内存放弃在安稳状态,没有回升,页面没有解体

  1. 进入态势概览页面,开启轮播页面后,切换到其余标签页或最小化浏览器

后果:内存放弃在安稳状态,没有回升,页面没有解体

  1. 放弃在态势概览页面,并开启轮播页面,不做其余操作,挂机一天一夜。

后果:内存放弃在 2G 左右,页面没有解体

总结

通过此次的内存溢出剖析,咱们意识了一些内存剖析工具及内存分析方法,也发现了代码中有余的中央,最初通过正确的办法解决了内存溢出的问题。心愿这篇文章能够对大家日后的工作有所帮忙。当然,这只是很小一部分,也可能有不正确的中央,欢送大家提出疑难一起探讨。

正文完
 0