JavaScript內存泄漏

內存泄漏簡介

內存泄漏(Memory Leak)是指程序中己動態分配的堆內存因爲某種緣由程序未釋放或沒法釋放,形成系統內存的浪費,致使程序運行速度減慢甚至系統崩潰等嚴重後果。程序員

內存泄漏缺陷具備隱蔽性、積累性的特徵,比其餘內存非法訪問錯誤更難檢測。由於內存泄漏的產生緣由是內存塊未被釋放,屬於遺漏型缺陷而不是過錯型缺陷。此外,內存泄漏一般不會直接產生可觀察的錯誤症狀,而是逐漸積累,下降系統總體性能,極端的狀況下可能使系統崩潰。數組

垃圾回收機制

最常使用的方法叫作"引用計數"(reference counting):語言引擎有一張"引用表",保存了內存裏面全部的資源(一般是各類值)的引用次數。若是一個值的引用次數是0,就表示這個值再也不用到了,所以能夠將這塊內存釋放。瀏覽器

const arr = [1, 2, 3, 4];
console.log('hello world');

上面代碼中,數組[1, 2, 3, 4]是一個值,會佔用內存。變量arr是僅有的對這個值的引用,所以引用次數爲1。儘管後面的代碼沒有用到arr,它仍是會持續佔用內存。數據結構

let arr = [1, 2, 3, 4];
console.log('hello world');
arr = null;

上面代碼中,arr重置爲null,就解除了對[1, 2, 3, 4]的引用,引用次數變成了0,內存就能夠釋放出來了。ide

內存泄漏的識別方法

經驗法則是,若是連續五次垃圾回收以後,內存佔用一次比一次大,就有內存泄漏。這就要求實時查看內存佔用。工具

瀏覽器識別

Chrome 瀏覽器查看內存佔用,按照如下步驟操做。性能

alt text

alt text

  1. 打開開發者工具,選擇 Timeline 面板
  2. 在頂部的Capture字段裏面勾選 Memory
  3. 點擊左上角的錄製按鈕。
  4. 在頁面上進行各類操做,模擬用戶的使用狀況。
  5. 一段時間後,點擊對話框的 stop 按鈕,面板上就會顯示這段時間的內存佔用狀況。

若是內存佔用基本平穩,接近水平,就說明不存在內存泄漏。spa

命令行識別

命令行可使用 Node 提供的process.memoryUsage方法。命令行

console.log(process.memoryUsage());
// { rss: 27709440,
//  heapTotal: 5685248,
//  heapUsed: 3449392,
//  external: 8772 }

process.memoryUsage返回一個對象,包含了 Node 進程的內存佔用信息。該對象包含四個字段,單位是字節,含義以下。code

alt text

  • rss(resident set size):全部內存佔用,包括指令區和堆棧。
  • heapTotal:"堆"佔用的內存,包括用到的和沒用到的。
  • heapUsed:用到的堆的部分。
  • external: V8 引擎內部的 C++ 對象佔用的內存。

判斷內存泄漏,以heapUsed字段爲準。

WeakSet 和 WeakMap

前面說過,及時清除引用很是重要。可是,你不可能記得那麼多,有時候一疏忽就忘了,因此纔有那麼多內存泄漏。

最好能有一種方法,在新建引用的時候就聲明,哪些引用必須手動清除,哪些引用能夠忽略不計,當其餘引用消失之後,垃圾回收機制就能夠釋放內存。這樣就能大大減輕程序員的負擔,你只要清除主要引用就能夠了。

ES6 考慮到了這一點,推出了兩種新的數據結構:WeakSet 和 WeakMap。它們對於值的引用都是不計入垃圾回收機制的,因此名字裏面纔會有一個"Weak",表示這是弱引用。詳細具體看阮一峯的ECMAScript 6 入門。

相關文章
相關標籤/搜索