1. 程式人生 > >最新前端記憶體洩漏的分析案例介紹

最新前端記憶體洩漏的分析案例介紹

在最近給客戶交付的一個專案中,客戶反映系統跑一段時間就會奔潰掉。我的第一直覺就是可能發生了記憶體洩漏。

復現bug

為了能夠讓bug復現,我讓開發的小夥,先把模擬系統在本地跑起來。要知道,bug復現是很重要的。bug復現,能夠讓開發人員直觀的感受到bug發生的過程。另外如果bug不能復現,程式設計師的反應可能是這樣的:

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

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

查詢原因

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

簡化程式

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

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

使用chrome的工具分析

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

memory標籤

memory標籤

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

記憶體記錄情況

記憶體記錄情況

點選其中的一個藍條,可以檢視區域性的記憶體情況,如下圖所示:

記憶體記錄情況2

記憶體記錄情況2

從中可以看到有array,system和Detached HTMLSpanElement。 我們知道Detached HTMLSpanElement表示已經脫離文件樹的dom元素,它也是導致記憶體洩漏的一個經常的誘因,點選Detached HTMLSpanElement,檢視詳情:

Detached HTML Element

Detached HTML Element

可以看到"_stringPool"這樣的一個數組物件,裡面放的就是Span元素,引用他的就是table,而且數量有372個之多,由於小例子使用的表格只有一行一列,這麼大的數量,肯定是記憶體洩漏導致,直接在瀏覽器列印這個pool,可以看出這個數量確實在一直增加(看index的情況):

記憶體洩漏

記憶體洩漏

至此,查到了是那個地方發生了記憶體洩漏。 根據這個線索,比較容易定位到程式的邏輯問題所在,並很快就解決了問題。 ps:同時還發現了table.__divPool也有記憶體洩漏的情況,通過同樣的方式定位到了這個問題並最終解決。