對於前端的「內存泄漏」這個東西,說實話我只在書上看到過:前端
閉包、匿名函數和事件綁定尤爲容易形成內存泄漏。瀏覽器
然而這些操做形成的「內存泄漏」到底是什麼樣子的?如何排查?雖然很好奇,卻不得而知。直到此次公司應用頻繁出現瀏覽器崩潰的狀況,我受命解決這個問題,纔開始研究內存泄漏的排查方法,及排查工具。markdown
我司的應用在客戶現場反饋過來的問題是:在某幾臺固定的電腦上頻繁出現瀏覽器崩潰的狀況。我問現場要了機器的配置,發現這些問題機器的可用運行內存,連三個 G 都沒有,在別的內存較大的機器上這種崩潰的狀況較少發生。閉包
若是瀏覽器頻繁出現「崩潰」、「卡頓」等狀況,則基本能夠判斷爲瀏覽器內存佔用較高,而 CPU 分配給瀏覽器的內存空間是很小且有限的,若是內存佔用瀕臨極限,就會出現卡頓,若是內存佔用溢出,瀏覽器就會崩潰。框架
Chrome 瀏覽器,F12 打開開發者工具,涉及公司機密,我就先找了阮一峯老師的 ES6 網站演示。函數
點擊這個按鈕啓動記錄,而後切換到網頁進行操做,錄製完成後點擊 stop 按鈕,開發者工具會從錄製時刻開始記錄當前應用的各項數據狀況工具
選中JS Heap
,下面展示出來的一條藍線,就是表明了這段記錄過程當中,JS 堆內存信息的變化狀況。網站
關於「堆」和「棧」的概念,簡單的說,開發者建立的對象都在堆裏,棧空間是留給系統來分配的spa
有大佬說,根據這條藍線就能夠判斷是否存在內存泄漏的狀況:若是這條藍線一直成上升趨勢,那基本就是內存泄漏了code
其實我以爲這麼講有失偏頗,JS 堆內存佔用率上升並不必定就是內存泄漏,只能說明有不少未被釋放的內存而已,至於這些內存是否真的在使用,仍是說確實是內存泄漏,還須要進一步排查。
開發者工具的 Memory 選項,能夠更精確地定位內存使用狀況。
當生成了第一個快照的時候,開發者工具窗口已經顯示了很詳細的內存佔用狀況。
字段解釋:
Constructor
— 佔用內存的資源類型Distance
— 當前對象到根的引用層級距離Shallow Size
— 對象所佔內存(不包含內部引用的其它對象所佔的內存)(單位:字節)Retained Size
— 對象所佔總內存(包含內部引用的其它對象所佔的內存)(單位:字節)將每項展開能夠查看更詳細的數據信息。
咱們再次切回網頁,繼續操做幾回,而後再次生成一個快照。
這邊須要特別注意這個 #Delta ,若是是正值,就表明新生成的內存多,釋放的內存少。其中的閉包項,若是是正值,就說明存在內存泄漏。
下面咱們到代碼裏找一個內存泄漏的問題:
單頁應用容易出現這個問題。
若是是普通網站,切換菜單頁面就刷新了,全部內存會被回收,進行再分配,不太會出現嚴重的內存泄漏問題。
最後,關於內存泄漏,我發現幾乎全部網站都存在這個問題,而且有不少的內存泄漏,都是第三方庫和框架的打包文件帶來的。因此說,對於內存泄漏,只要不是特別嚴重,開發者是沒有單獨處理的必要的。
然而我司的應用就另當別論了,,
別問我有多少內存泄漏。
五十三萬個,我日。。