深入淺出nodejs學習筆記--第五章 內存控制

首先聲明一下,這個內存控制指的是V8引擎的內存控制,聽起來很高大上,平時web開發可能不會去考慮瀏覽器的內存控制機制,但是其實我們在學習js的時候就有多少瞭解到垃圾回收和內存監控這相關的知識。


Js的垃圾回收機制和內存控制

《JavaScript高級程序設計》(第三版)裏也有提到了js的垃圾回收機制和內存回收問題,這裏簡單的回想一下:

我們知道,js和java的一個共同點就是有自己的垃圾回收機制,所以他們不用像C/C++程序員一樣在編寫代碼的時候去關心內存的分配與釋放的問題。關於js的垃圾回收機制,主要有以下兩種:

  • 標記清除: 這個很容易理解,就是當你在函數內聲明一個變量,那麼在函數執行的時候,就將該變量進行標記,標記爲進入,函數執行完畢就標記爲離開,進入標記的是不可以被回收的
  • 引用計數: 更簡單的,就是一個變量被使用的次數,用到一次就加一,數目小於多少的就給予清除

那麼如何管理內存呢?

前面也說了,因爲有自動的垃圾回收機制,所以程序員不用去操心內存管理的問題,但是要注意的一點就是,js的可用內存是很小的,或者說是遠遠小於桌面程序的可使用內存(這個後面再說),所以爲了確保佔用最少的內存可以讓頁面獲得更好地性能,最佳方式就是爲執行中的代碼只保存必要的數據,一旦數據不再有用,就將其釋放(比如設置其值爲null來釋放引用),這樣做的目的是解除變量的引用從而使垃圾收集機制在下次運行時將其回收(垃圾回收機制是按照固定的時間間隔或者預設的時間進行處理的,所以這個時間的長短也要考慮性能問題)


V8的內存分配

那麼說完了js中的內存管理,那麼就到了我們今天討論的V8引擎,瀏覽器內的內存控制。

內存限制

首先呢,通過Node使用內存時是只可以使用部分內存的,這個大小大概在(64位系統下是1.4GB,32位系統下是0.7GB),在V8中,所有的js對象都是通過堆來進行分配的,這個可以通過控制檯輸入 process.memoryUsage() 方法查看。執行此操作需要切換到node命令執行環境。

V8的內存分配

在V8中,主要將內存分爲新生代和老生代兩種,新生代中的對象爲存活時間比較短的對象,老生代中的對象爲存活時間較長或常駐內存的對象。V8的堆內存的大小就是新生代加上老生代的大小。而V8關於內存限制的算法主要有兩種,這裏只簡單提及一下。

一種是犧牲空間換時間的算法,叫做Scavenge算法,通過該算法來回收新生代中的對象,原理就是講新生代的內存一分爲二,A和B,A和B永遠都是一個處於空閒狀態,一個處於使用狀態,在垃圾回收的時,會檢查使用中的A,如果A中存在還使用的對象啥的,就複製給空閒中的B,然後A中沒有被使用對象啥的就會被清除,如此往復,達到垃圾清除的目的,但是這個算法有一個問題就是,如果A中存活的還在使用的對象是比較少的,那麼在進行復制時,這個效率是很高的,但如果A中存活的對象比較大,效率就不能滿足需求了。

這就牽扯到另外一種算法了,另外一種就是 Mark-SweepMark-Compact ,標記清除方法,這個很簡單,就是沒有一分爲二的概念,直接查找內存中的存活或者死亡的對象,然後添加一個標記,然後等垃圾回收進行清除,需要注意的一點,爲了避免標記清除造成的內存碎片化,需要在對象被標記死亡後進行一次整理,將或者的對象往一端靠攏,舉個例子就是好人站內存左邊,壞人站內存右邊,等會收拾壞人。

如何高效的使用內存

這一塊兒呢,只需要注意作用域和閉包帶來的問題就好,跟js中的優化是一樣的,不作介紹。

內存泄漏

內存泄漏是程序員在與內存打交道時一定要注意的問題,通常情況下,造成內存泄露的原因主要有三個: 緩存、 隊列消費不及時、 作用域未釋放

基於此,避免造成內存泄漏的方案也有以下兩種:

  • 不要將內存當做緩存: 說不要太過了,儘量不要吧;
  • 關注隊列狀態: 隊列狀態造成的內存泄漏其實不容易發生,因爲大多數情況是使用的速度是大於生產的速度的,是不會有庫存的。但是二班情況,如果出現了,就很難排查,所以對於隊列狀態引起的內存泄漏,應監控隊列的長度,如果長度超過了一定限制,就給出異常拒絕再使用內存。

前端新手,弱雞一枚,如有錯誤,請指正,謝謝!

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