前端內存泄漏的分析案例

在最近給客戶交付的一個項目中,客戶反映系統跑一段時間就會奔潰掉。我的第一直覺就是可能發生了內存泄漏。
##復現bug
爲了能夠讓bug復現,我讓開發的小夥,先把模擬系統在本地跑起來。要知道,bug復現是很重要的。bug復現,能夠讓開發人員直觀的感受到bug發生的過程。另外如果bug不能復現,程序員的反應可能是這樣的:

我的這邊是好的呀,沒有什麼問題。
哎呀,是不是你的使用方法不對啊。

看到了嗎,如果bug不能復現,會直接極大的減少程序員想要修復bug的意願的。
我後來問他,測試的怎麼樣,他說沒有問題呀。我問題跑了多久,他說有一會兒吧,看沒問題就關閉了。
一般來說,內存泄漏最終導致奔潰的需要挺長一段時間的,所以我告訴他一直跑,跑到奔潰爲止。
後來第二天,他說果然奔潰了。

查找原因

因爲更新了的版本纔出現內存泄漏的問題,所以有理由懷疑,就是新增加的功能導致的內存泄漏。 新加的功能是,在一個TWaver的表格中,部分單元格中使用echart 圖表來繪製。而由於代碼中每次刷新的都會調用echart.init方法重新創建。導致原來創建的echart實例中創建的一些變量不能釋放,所以這裏懷疑,echart 如果反覆刪除並創建會導致內存泄漏。所以讓開發人員改成了緩存的方案。
當然由於TWaver表格的內部機制,會在重新繪製的時候,移除上一次單元格的內容,並移除內容所有父子關係。這個問題導致了,緩存方案失效。 最終的解決方案是重寫了這個移除方法,不解除移除內容的父子關係。
到此爲止,應該問題是解決了。讓小夥伴改進後,繼續把模擬系統一直跑起來。 很不幸的是,第二天仍然奔潰。由於此時並不能直觀的看出問題所在,所以需要使用一些技巧了。

簡化程序

可以確定的是,還是表格的問題導致的內存泄漏,爲了避免干擾,讓小夥伴把表格的核心內容拉出來寫兩個一個demo。 這樣就可以專注於表格相關問題的定位了。

在解決一些大項目的問題的時候,如果發現一些難定位的問題,可以考慮把程序簡化,抽出有問題的代碼部分寫小的例子。方便問題的定位,排除不必要的干擾。

使用chrome的工具分析

首先把小夥伴寫的小例子跑起來,然後打開chrome的控制檯。點擊memory標籤:
memory標籤

選擇Allocation instrumentation on timeline,點擊start,開始錄製內存的記錄情況,會發現有一些藍色的條,永遠不會變暗,表示這部分內存始終未被回收:
內存記錄情況

點擊其中的一個藍條,可以查看局部的內存情況,如下圖所示:
內存記錄情況2

從中可以看到有array,system和Detached HTMLSpanElement。 我們知道Detached HTMLSpanElement表示已經脫離文檔樹的dom元素,它也是導致內存泄漏的一個經常的誘因,點擊Detached HTMLSpanElement,查看詳情:
Detached HTML Element

可以看到"_stringPool"這樣的一個數組對象,裏面放的就是Span元素,引用他的就是table,而且數量有372個之多,由於小例子使用的表格只有一行一列,這麼大的數量,肯定是內存泄漏導致,直接在瀏覽器打印這個pool,可以看出這個數量確實在一直增加(看index的情況):
內存泄漏
至此,查到了是那個地方發生了內存泄漏。 根據這個線索,比較容易定位到程序的邏輯問題所在,並很快就解決了問題。
ps:同時還發現了table.__divPool也有內存泄漏的情況,通過同樣的方式定位到了這個問題並最終解決。

問題出在小夥伴對於renderCell方法的重載和release方法的重載,這個涉及到TWaver的內部邏輯,此處就不詳細說明了。

歡迎關注公衆號:
ITman彪叔公衆號

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章