首頁 >web前端 >js教程 >nodejs垃圾回收的詳細介紹

nodejs垃圾回收的詳細介紹

不言
不言轉載
2018-10-25 16:08:002190瀏覽

這篇文章帶給大家的內容是關於nodejs垃圾回收的詳細介紹,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

nodejs的垃圾回收機制是由v8引擎自動管理的。

nodejs的記憶體限制

在一般的後端語言(php)來說,記憶體的使用上是沒有限制的,但對於nodejs來說只能使用系統的部分----64位元系統為1.4G,32位元系統位0.7G。這時如果你要處理個3G檔進行資料分析,即使系統的記憶體為8G,在該nodejs進程記憶體還是會溢位。

造成上面這個問題主要是因為nodejs是基於v8的,nodejs是透過v8自己的方式來管理記憶體的。那v8為什麼要限制堆記憶體的大小呢?原因有2:

1、表層原因:v8是為瀏覽器設計的,不太可能遇到大記憶體的情境。

2.深層原因:v8垃圾回收機制的限制。以1.5G的堆內存為例,v8做一次小的垃圾回收需要50ms,做一次非增量的垃圾回收要1s。垃圾回收時會造成js的執行緒的暫停,在這樣的時間花銷下,應用的效能、反應能力會直線下降。

記憶體限制是可以開啟的:
 --max-old-space-size(老生代)
 --max-new-space-size(新生代)
 v8堆記憶體大小= 老生代新生代

v8垃圾回收機制
v8垃圾回收主要是基於分代垃圾回收機制。依物件的存活時間將記憶體的垃圾回收進行不同的分代,分別對不同的分代記憶體進行不同的演算法。

新生代--->存活時間較短的物件
老生代--->存活時間較長或常駐記憶體的物件
上面也說過,nodejs堆內存的大小是新生代記憶體空間加上老生代記憶體空間。

新生代演算法
新生代主要是透過scavenge演算法進行垃圾回收。

這是一種採用複製的方式來實現垃圾回收,將堆記憶體一分為二,每個空間稱為semispace。在這2個semispace空間中,只有一個處於使用中(稱為from空間),另一個則處於空閒(稱為to空間)。開始分配時先從from空間開始,當開始垃圾回收時,也是從from空間開始檢查存活對象,把存活對象複製到to空間,而非存活對象佔用的空間就會被釋放。完成複製後,from空間和to空間角色對調。
從上面的過程可以知道,scavenge的缺點就是只使用了一半的堆內存,犧牲空間獲取時間。

老生代透過mark-sweep、mark-comopact演算法。

mark-sweep標記清除,分為標記、清除2個階段。 mark-sweep先在標記階段遍歷堆記憶體中的所有對象,並標記存活的對象;在清除階段把沒有被標記的對象清除。可以看出,scavenge只複製存活的對象,mark-sweep只清理死亡的對象。因為在新生代中存活的對象佔用小部分,而在老生代中死亡對象佔用小部分,這是這2中算法高效的原因。

Mark-compact標記整理,mark-sweep中會出現一個問題,回收後,對記憶體會出現不連續的狀態(記憶體片段)。記憶體碎片會對後續的記憶體分配造成影響,因為會有這樣一種情況:需要分配個大內存,而所有記憶體碎片都無法完成分配,這會提前觸發垃圾回收,而這個回收時不必要的。 Mark-compact是在Mark-sweep基礎上演變而來的,它主要區別在於:物件被標記後,在整理的過程中會將存活的物件都往一端移動,移動完成後直接清除。

小結:在正常的使用過程中,v8的記憶體限制還是夠用的,但nodejs的垃圾回收、單執行緒還是會影響效能。想要高性能,需要讓垃圾回收盡量小。在實際的開發中要老生代對象的使用,如實現web服務的會話(session),一般會通過內存來存儲(數組),在訪問量大的情況下會導致老生代對象劇增,有可能造成溢出。如果要處理大記憶體的數據,例如讀取3G的文件,我們會透過可讀流的pipe()方法,這樣就不會受到v8記憶體的限制影響,提高了nodejs程式的健全性。

#

以上是nodejs垃圾回收的詳細介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除