引言
在開發(fā)綜合治理平臺(tái)態(tài)勢概覽的大屏頁面的過程攒巍,遇到了頁面崩潰的問題,本帖子記錄了崩潰的原因分析和解決方案。
問題
打開綜合治理平臺(tái)当船,進(jìn)入態(tài)勢概覽頁面,停留在此頁面一段時(shí)間默辨,會(huì)出現(xiàn)如下圖所示的頁面崩潰的情況德频。
原因分析
注:以下操作環(huán)境建議在瀏覽器隱身模式下進(jìn)行,防止其他因素干擾
使用工具
根據(jù)頁面崩潰的提示缩幸,可以初步判定是頁面內(nèi)存溢出導(dǎo)致的崩潰壹置,為了驗(yàn)證內(nèi)存是否溢出竞思,可以使用 Chrome 瀏覽器自帶的工具分析驗(yàn)證。這里介紹三種工具的使用钞护,可以結(jié)合實(shí)際需求來使用盖喷。
- 任務(wù)管理器
-
打開方式:
file -
界面:
file
3)使用方式:
任務(wù)管理器的使用方法最為簡單,打開需要分析的頁面难咕,直接觀察內(nèi)存占用空間與 JavaScript 使用的內(nèi)存即可课梳。如果這兩個(gè)數(shù)據(jù)持續(xù)上升,說明內(nèi)存正在泄漏余佃。
-
開發(fā)者工具 Performance 面板
1) 打開方式:
按 F12 打開開發(fā)者工具暮刃,選擇 Performance 欄
2) 界面:
file
3) 使用方式:
打開需要分析的頁面,等頁面穩(wěn)定下來后爆土,點(diǎn)擊 Performance 左上角的錄制按鈕開始錄制椭懊,它會(huì)保存下頁面的快照、JS Heap步势、Document灾搏、Nodes、Listener立润、GPU Memory等信息狂窑。錄制一段時(shí)間(最好在一分鐘以上)后,停止錄制桑腮,等待工具生成報(bào)告泉哈。 -
開發(fā)者工具 Memory 面板
1) 打開方式:
按 F12 打開開發(fā)者工具,選擇 Memory 欄
2) 界面:
file
3) 使用方式:
這個(gè)工具的使用方式最為復(fù)雜破讨,這里只簡單介紹下 Heap snapshot 的使用丛晦,感興趣的可以自行搜索其他使用方式。
首先提陶,打開需要分析內(nèi)存的頁面烫沙,點(diǎn)擊工具左上方的錄制按鈕,生成分析報(bào)告隙笆。
其次锌蓄,進(jìn)行一些可能導(dǎo)致內(nèi)存上升的操作后,再次點(diǎn)擊錄制按鈕撑柔,生成分析報(bào)告瘸爽。
最后,我們有了兩份分析報(bào)告铅忿,通過菜單欄的下拉框選擇 Comparison 過濾分析結(jié)果剪决。觀察 #New、#Deleted、#Delta 這三列柑潦,分別代表新增對象數(shù)享言、刪除對象數(shù)、新增數(shù)與刪除數(shù)的差值渗鬼,找到那些只有新增担锤,沒有刪除的對象,看看是被誰引用了乍钻,據(jù)此來找到可能導(dǎo)致內(nèi)存溢出的代碼肛循。
file
確定內(nèi)存溢出原因
打開態(tài)勢概覽頁面后,通過任務(wù)管理器觀察頁面使用的內(nèi)存银择,發(fā)現(xiàn)內(nèi)存是持續(xù)上升的多糠,這時(shí)再通過 Performance 工具進(jìn)一步分析。
以下是 Performance 的分析結(jié)果:
通過分析結(jié)果可以看到浩考,內(nèi)存資源在持續(xù)上升夹孔,再進(jìn)一步觀察結(jié)果,可以發(fā)現(xiàn)內(nèi)存上升是存在一個(gè)階梯式的上升周期的析孽,為什么會(huì)產(chǎn)生這種現(xiàn)象呢搭伤?放大內(nèi)存上升的部分進(jìn)一步分析看看:
上圖顯示了內(nèi)存上升部分細(xì)節(jié),把鼠標(biāo)移動(dòng)到頁面快照上袜瞬,可以清楚地看到怜俐,當(dāng)上一個(gè)大屏頁面輪播到下一個(gè)頁面時(shí),內(nèi)存就會(huì)上升并且不會(huì)再下降到之前的水平〉擞龋現(xiàn)在已經(jīng)有理由懷疑是頁面輪播引起的內(nèi)存溢出拍鲤,所以,通過暫停頁面輪播汞扎,再進(jìn)行一次 Performance 分析季稳,看看分析結(jié)果:
通過上圖可以看到,暫停頁面輪播后澈魄,并沒有明顯的上升趨勢景鼠,說明瀏覽器可以正常回收內(nèi)存痹扇,并沒有溢出铛漓。至此,已經(jīng)可以確定當(dāng)頁面輪播時(shí)內(nèi)存會(huì)溢出帘营。
分析內(nèi)存溢出對象
經(jīng)過第二步的分析票渠,已經(jīng)知道了大屏頁面切換會(huì)導(dǎo)致內(nèi)存升高逐哈,利用這個(gè)證據(jù)芬迄,用 Memory 工具去進(jìn)一步分析,找到那些被引用本該被釋放昂秃,但實(shí)際沒有的釋放的對象禀梳。
首先杜窄,打開態(tài)勢概覽頁面,先暫停頁面輪播切換算途,停留在總體態(tài)勢頁面塞耕,待頁面加載完成,然后打開 Memory 工具嘴瓤,點(diǎn)擊錄制按鈕分析總體態(tài)勢頁面的內(nèi)存扫外。分析完成后,手動(dòng)切換到風(fēng)險(xiǎn)態(tài)勢頁面或者其他大屏頁面廓脆,再切換回總體態(tài)勢頁面筛谚,然后在 Memory 工具中再次點(diǎn)擊錄制按鈕分析頁面切換之后的內(nèi)存。完成以上操作之后停忿,就得到了兩份分析報(bào)告驾讲,分別是內(nèi)存上升前和上升后的,在 Memory 工具的菜單欄下拉框中選擇 Comparison席赂,看看到底是哪些家伙占用了內(nèi)存吮铭!
來分析上面的結(jié)果圖,首先颅停,頁面上有各種類型的對象谓晌,點(diǎn)擊對象可以看到對象具體的引用信息,我們的任務(wù)是通過對象引用信息找到一些蛛絲馬跡癞揉。我們可以搜索 detached 開頭歸類的對象扎谎,也就是那些在內(nèi)存中但是沒有在頁面進(jìn)行渲染的元素。選擇一個(gè)烧董,可以看到它的詳細(xì)引用信息:
很明顯毁靶,ehcarts 引用了這個(gè)對象,而這個(gè)對象連同它的引用逊移,理應(yīng)是在頁面切換之后被銷毀了的预吆,既然他沒有銷毀,說明我們的代碼是有問題的胳泉。接下來要做的是拐叉,找出 ehcarts 引用的對象沒有被銷毀的原因,修改相關(guān)代碼扇商,再驗(yàn)證凤瘦。
解決方案
使用正確的 echarts 實(shí)例銷毀方法
根據(jù)上面的原因分析,我們知道是 echarts 引用的對象沒有正常被銷毀案铺,那么很簡單蔬芥,我們只要嘗試正確銷毀 echarts 實(shí)例就好了。進(jìn)入到我們的 ehcarts 組件代碼,定位到 beforDestory 鉤子笔诵,可以看到返吻,已經(jīng)有一段代碼對 echarts 實(shí)例進(jìn)行釋放了。
進(jìn)入 echarts 官網(wǎng)查詢銷毀實(shí)例的相關(guān) api乎婿,發(fā)現(xiàn)
.clear()
方法只是清空了實(shí)例测僵,并沒有銷毀,而.dispose()
方法才會(huì)銷毀實(shí)例谢翎。答案到這里已經(jīng)呼之欲出了捍靠,我們項(xiàng)目中之前一直用的是
.clear()
方法清空 echarts 實(shí)例對象,而不是用.dispose()
銷毀森逮,所以 echarts 實(shí)例并沒有被正常銷毀剂公,當(dāng)我們頻繁地切換頁面的時(shí)候,echarts 實(shí)例就會(huì)不斷的累加吊宋,占用的內(nèi)存也會(huì)隨之增加纲辽。所以,這里建議璃搜,以后我們封裝 echarts 組件的時(shí)候拖吼,統(tǒng)一使用.dispose()
方法銷毀組件。頁面隱藏時(shí)停止定時(shí)器任務(wù)
你以為到這里就結(jié)束了嗎这吻?事情沒有那么簡單吊档!在搜索內(nèi)存溢出解決方案的時(shí)候,在網(wǎng)上看到了一篇文章:https://www.cnblogs.com/zdd2017/p/11777822.html
再次通過 Performance 工具分析驗(yàn)證唾糯,結(jié)果如下:
果然怠硼,內(nèi)存又在持續(xù)增加,那么就使用網(wǎng)上分享的方法解決這個(gè)問題移怯,添加一個(gè)標(biāo)簽切換的監(jiān)聽函數(shù)香璃,在離開頁面時(shí),把頁面的定時(shí)器清除舟误,回來頁面時(shí)重新開啟定時(shí)器葡秒,這樣就可以了。
結(jié)果
-
保持在態(tài)勢概覽頁面嵌溢,并開啟輪播頁面眯牧,使用 Permermance 工具進(jìn)行內(nèi)存分析
結(jié)果:內(nèi)存保持在平穩(wěn)狀態(tài),沒有上升赖草,頁面沒有崩潰
file -
進(jìn)入態(tài)勢概覽頁面学少,開啟輪播頁面后,切換到其他標(biāo)簽頁或最小化瀏覽器
結(jié)果:內(nèi)存保持在平穩(wěn)狀態(tài)秧骑,沒有上升版确,頁面沒有崩潰
file 保持在態(tài)勢概覽頁面扣囊,并開啟輪播頁面,不做其他操作阀坏,掛機(jī)一天一夜如暖。
結(jié)果:內(nèi)存保持在 2G 左右笆檀,頁面沒有崩潰
總結(jié)
通過此次的內(nèi)存溢出分析忌堂,我們認(rèn)識(shí)了一些內(nèi)存分析工具及內(nèi)存分析方法,也發(fā)現(xiàn)了代碼中不足的地方酗洒,最后通過正確的方法解決了內(nèi)存溢出的問題士修。希望這篇文章可以對大家日后的工作有所幫助。當(dāng)然樱衷,這只是很小一部分棋嘲,也可能有不正確的地方,歡迎大家提出疑問一起探討矩桂。